Repository: BarRaider/obs-websocket-dotnet Branch: master Commit: f0ad1fefe160 Files: 131 Total size: 819.2 KB Directory structure: gitextract_ua3ds4ck/ ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── feedback-or-support-request.md │ └── workflows/ │ └── dotnet-core-desktop.yml ├── .gitignore ├── LICENSE ├── README.md ├── TestClient/ │ ├── AdvancedWindow.Designer.cs │ ├── AdvancedWindow.cs │ ├── AdvancedWindow.resx │ ├── App.config │ ├── LICENSE.md │ ├── MainWindow.Designer.cs │ ├── MainWindow.cs │ ├── MainWindow.resx │ ├── Program.cs │ ├── Properties/ │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ ├── Settings.Designer.cs │ │ └── Settings.settings │ ├── TestClient.csproj │ └── packages.config ├── obs-websocket-dotnet/ │ ├── Communication/ │ │ ├── MessageFactory.cs │ │ ├── MessageTypes.cs │ │ ├── OBSAuthInfo.cs │ │ ├── ObsCloseCodes.cs │ │ ├── ObsDisconnectionInfo.cs │ │ └── ServerMessage.cs │ ├── Events.cs │ ├── Exceptions.cs │ ├── IOBSWebsocket.cs │ ├── LICENSE.md │ ├── OBSWebsocket.cs │ ├── OBSWebsocket_Requests.cs │ ├── Types/ │ │ ├── Events/ │ │ │ ├── CurrentPreviewSceneChangedEventArgs.cs │ │ │ ├── CurrentProfileChangedEventArgs.cs │ │ │ ├── CurrentProfileChangingEventArgs.cs │ │ │ ├── CurrentSceneCollectionChangedEventArgs.cs │ │ │ ├── CurrentSceneCollectionChangingEventArgs.cs │ │ │ ├── CurrentSceneTransitionChangedEventArgs.cs │ │ │ ├── CurrentSceneTransitionDurationChangedEventArgs.cs │ │ │ ├── InputActiveStateChangedEventArgs.cs │ │ │ ├── InputAudioBalanceChangedEventArgs.cs │ │ │ ├── InputAudioMonitorTypeChangedEventArgs.cs │ │ │ ├── InputAudioSyncOffsetChangedEventArgs.cs │ │ │ ├── InputAudioTracksChangedEventArgs.cs │ │ │ ├── InputCreatedEventArgs.cs │ │ │ ├── InputMuteStateChangedEventArgs.cs │ │ │ ├── InputNameChangedEventArgs.cs │ │ │ ├── InputRemovedEventArgs.cs │ │ │ ├── InputShowStateChangedEventArgs.cs │ │ │ ├── InputVolumeChangedEventArgs.cs │ │ │ ├── InputVolumeMetersEventArgs.cs │ │ │ ├── MediaInputActionTriggeredEventArgs.cs │ │ │ ├── MediaInputPlaybackEndedEventArgs.cs │ │ │ ├── MediaInputPlaybackStartedEventArgs.cs │ │ │ ├── ProfileListChangedEventArgs.cs │ │ │ ├── ProgramSceneChangedEventArgs.cs │ │ │ ├── RecordStateChangedEventArgs.cs │ │ │ ├── ReplayBufferSavedEventArgs.cs │ │ │ ├── ReplayBufferStateChangedEventArgs.cs │ │ │ ├── SceneCollectionListChangedEventArgs.cs │ │ │ ├── SceneCreatedEventArgs.cs │ │ │ ├── SceneItemCreatedEventArgs.cs │ │ │ ├── SceneItemEnableStateChangedEventArgs.cs │ │ │ ├── SceneItemListReindexedEventArgs.cs │ │ │ ├── SceneItemLockStateChangedEventArgs.cs │ │ │ ├── SceneItemRemovedEventArgs.cs │ │ │ ├── SceneItemSelectedEventArgs.cs │ │ │ ├── SceneItemTransformEventArgs.cs │ │ │ ├── SceneListChangedEventArgs.cs │ │ │ ├── SceneNameChangedEventArgs.cs │ │ │ ├── SceneRemovedEventArgs.cs │ │ │ ├── SceneTransitionEndedEventArgs.cs │ │ │ ├── SceneTransitionStartedEventArgs.cs │ │ │ ├── SceneTransitionVideoEndedEventArgs.cs │ │ │ ├── SourceFilterCreatedEventArgs.cs │ │ │ ├── SourceFilterEnableStateChangedEventArgs.cs │ │ │ ├── SourceFilterListReindexedEventArgs.cs │ │ │ ├── SourceFilterNameChangedEventArgs.cs │ │ │ ├── SourceFilterRemovedEventArgs.cs │ │ │ ├── StreamStateChangedEventArgs.cs │ │ │ ├── StudioModeStateChangedEventArgs.cs │ │ │ ├── UnsupportedEventArgs.cs │ │ │ ├── VendorEventArgs.cs │ │ │ └── VirtualcamStateChangedEventArgs.cs │ │ ├── FilterReorderItem.cs │ │ ├── FilterSettings.cs │ │ ├── GetProfileListInfo.cs │ │ ├── GetSceneListInfo.cs │ │ ├── GetTransitionListInfo.cs │ │ ├── Input.cs │ │ ├── InputBasicInfo.cs │ │ ├── InputBrowserSourceSettings.cs │ │ ├── InputFFMpegSettings.cs │ │ ├── InputSettings.cs │ │ ├── InputVolume.cs │ │ ├── KeyModifier.cs │ │ ├── MediaInputStatus.cs │ │ ├── Monitor.cs │ │ ├── OBSHotkey.cs │ │ ├── OBSScene.cs │ │ ├── OBSStats.cs │ │ ├── OBSVersion.cs │ │ ├── OBSVideoSettings.cs │ │ ├── OutputState.cs │ │ ├── OutputStateChanged.cs │ │ ├── OutputStatus.cs │ │ ├── RecordStateChanged.cs │ │ ├── RecordingStatus.cs │ │ ├── SceneBasicInfo.cs │ │ ├── SceneItemBoundsType.cs │ │ ├── SceneItemDetails.cs │ │ ├── SceneItemSourceType.cs │ │ ├── SceneItemTransformInfo.cs │ │ ├── SourceActiveInfo.cs │ │ ├── SourceTracks.cs │ │ ├── StreamingService.cs │ │ ├── StreamingServiceSettings.cs │ │ ├── TransitionOverrideInfo.cs │ │ ├── TransitionSettings.cs │ │ ├── VirtualCamStatus.cs │ │ └── VolumeInfo.cs │ ├── obs-websocket-dotnet.csproj │ └── obs-websocket-dotnet.xml ├── obs-websocket-dotnet-tests/ │ ├── UnitTest_OBSWebsocket.cs │ ├── UnitTest_Types.cs │ ├── obs-websocket-dotnet-tests.csproj │ └── packages.config └── obs-websocket-dotnet.sln ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ ############################################################################### # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto ############################################################################### # Set default behavior for command prompt diff. # # This is need for earlier builds of msysgit that does not have it on by # default for csharp files. # Note: This is only used by command line ############################################################################### #*.cs diff=csharp ############################################################################### # Set the merge driver for project and solution files # # Merging from the command prompt will add diff markers to the files if there # are conflicts (Merging from VS is not affected by the settings below, in VS # the diff markers are never inserted). Diff markers may cause the following # file extensions to fail to load in VS. An alternative would be to treat # these files as binary and thus will always conflict and require user # intervention with every merge. To do so, just uncomment the entries below ############################################################################### #*.sln merge=binary #*.csproj merge=binary #*.vbproj merge=binary #*.vcxproj merge=binary #*.vcproj merge=binary #*.dbproj merge=binary #*.fsproj merge=binary #*.lsproj merge=binary #*.wixproj merge=binary #*.modelproj merge=binary #*.sqlproj merge=binary #*.wwaproj merge=binary ############################################################################### # behavior for image files # # image files are treated as binary by default. ############################################################################### #*.jpg binary #*.png binary #*.gif binary ############################################################################### # diff behavior for common document formats # # Convert binary document formats to text before diffing them. This feature # is only available from the command line. Turn it on by uncommenting the # entries below. ############################################################################### #*.doc diff=astextplain #*.DOC diff=astextplain #*.docx diff=astextplain #*.DOCX diff=astextplain #*.dot diff=astextplain #*.DOT diff=astextplain #*.pdf diff=astextplain #*.PDF diff=astextplain #*.rtf diff=astextplain #*.RTF diff=astextplain ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: BarRaider patreon: BarRaider custom: paypal.me/BarRaider ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: "[BUG]" labels: '' assignees: '' --- **Issue Type** # Only keep ONE of the options below: - Bug - Feature Request **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Versions** OBS Version: OBS WebSocket Version: OBS WebSocket Dotnet (this library) Version: OS: [e.g. Windows 10] **Additional context** Add any other context about the problem here. ================================================ FILE: .github/ISSUE_TEMPLATE/feedback-or-support-request.md ================================================ --- name: Feedback or Support request about: Anything that ISN'T a bug title: "[ISSUE]" labels: '' assignees: '' --- **Issue Type** # Only keep ONE of the options below: - Bug - Feature Request - Support Issue **Describe the issue** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Versions** OBS Version: OBS WebSocket Version: OBS WebSocket Dotnet (this library) Version: OS: [e.g. Windows 10] **Additional context** Add any other context about the problem here. ================================================ FILE: .github/workflows/dotnet-core-desktop.yml ================================================ # This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. # This workflow will build, test, sign and package a WPF or Windows Forms desktop application # built on .NET Core. # To learn how to migrate your existing application to .NET Core, # refer to https://docs.microsoft.com/en-us/dotnet/desktop-wpf/migration/convert-project-from-net-framework # # To configure this workflow: # # 1. Configure environment variables # GitHub sets default environment variables for every workflow run. # Replace the variables relative to your project in the "env" section below. # # 2. Signing # Generate a signing certificate in the Windows Application # Packaging Project or add an existing signing certificate to the project. # Next, use PowerShell to encode the .pfx file using Base64 encoding # by running the following Powershell script to generate the output string: # # $pfx_cert = Get-Content '.\SigningCertificate.pfx' -Encoding Byte # [System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt' # # Open the output file, SigningCertificate_Encoded.txt, and copy the # string inside. Then, add the string to the repo as a GitHub secret # and name it "Base64_Encoded_Pfx." # For more information on how to configure your signing certificate for # this workflow, refer to https://github.com/microsoft/github-actions-for-desktop-apps#signing # # Finally, add the signing certificate password to the repo as a secret and name it "Pfx_Key". # See "Build the Windows Application Packaging project" below to see how the secret is used. # # For more information on GitHub Actions, refer to https://github.com/features/actions # For a complete CI/CD sample to get started with GitHub Action workflows for Desktop Applications, # refer to https://github.com/microsoft/github-actions-for-desktop-apps name: obs-websocket-dotnet Tests on: push: branches: [ master ] pull_request: branches: [ master ] jobs: build: strategy: matrix: configuration: [ Release ] runs-on: windows-latest # For a list of available runner types, refer to # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on env: Solution_Name: obs-websocket-dotnet.sln # Replace with your solution name, i.e. MyWpfApp.sln. Test_Project_Path: obs-websocket-dotnet-tests\obs-websocket-dotnet-tests.csproj # Replace with the path to your test project, i.e. MyWpfApp.Tests\MyWpfApp.Tests.csproj. #Wap_Project_Directory: your-wap-project-directory-name # Replace with the Wap project directory relative to the solution, i.e. MyWpfApp.Package. #Wap_Project_Path: your-wap-project-path # Replace with the path to your Wap project, i.e. MyWpf.App.Package\MyWpfApp.Package.wapproj. steps: - name: Checkout uses: actions/checkout@v2 with: fetch-depth: 0 # Install the .NET Core workload - name: Install .NET Core uses: actions/setup-dotnet@v4 with: dotnet-version: 9.0.x # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild - name: Setup MSBuild.exe uses: microsoft/setup-msbuild@v1.0.2 # Execute all unit tests in the solution - name: Execute unit tests run: dotnet test # Restore the application to populate the obj folder with RuntimeIdentifiers - name: Restore the application run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration env: Configuration: ${{ matrix.configuration }} ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.rsuser *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Mono auto generated files mono_crash.* # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ [Aa][Rr][Mm]/ [Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ [Ll]ogs/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUnit *.VisualState.xml TestResult.xml nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ # .NET Core project.lock.json project.fragment.lock.json artifacts/ # StyleCop StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c *_h.h *.ilk *.meta *.obj *.iobj *.pch *.pdb *.ipdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *_wpftmp.csproj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # Visual Studio Trace Files *.e2e # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json # Visual Studio code coverage results *.coverage *.coveragexml # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # NuGet Symbol Packages *.snupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx *.appxbundle *.appxupload # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !?*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings orleans.codegen.cs # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ *.rptproj.bak # SQL Server files *.mdf *.ldf *.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings *.rptproj.rsuser *- [Bb]ackup.rdl *- [Bb]ackup ([0-9]).rdl *- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat node_modules/ # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # CodeRush personal settings .cr/personal # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc # Cake - Uncomment if you are using it # tools/** # !tools/packages.config # Tabs Studio *.tss # Telerik's JustMock configuration file *.jmconfig # BizTalk build output *.btp.cs *.btm.cs *.odx.cs *.xsd.cs # OpenCover UI analysis results OpenCover/ # Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log *.binlog # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder .mfractor/ # Local History for Visual Studio .localhistory/ # BeatPulse healthcheck temp database healthchecksdb # Backup folder for Package Reference Convert tool in Visual Studio 2017 MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ .idea/ ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2021 BarRaider Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # obs-websocket-dotnet ![Build status](https://github.com/Palakis/obs-websocket-dotnet/workflows/obs-websocket-dotnet%20Tests/badge.svg)  Releases: [![NuGet](https://img.shields.io/nuget/v/obs-websocket-dotnet.svg?style=flat)](https://www.nuget.org/packages/obs-websocket-dotnet) Official .NET library (written in C#) to communicate with an obs-websocket server. This library is available on the [NuGet gallery](https://www.nuget.org/packages/obs-websocket-dotnet) See the `TestClient` project for a working example. ## New in v5.0.1 * Fixes for deserialization issues in MediaInputStatus * Allow OBSVideoSettings to be updated via the API * New ILogger support instead of writing to console * New UnsupportedEvent event * Updated to netstandard 2.1 Please report issues/bugs via the [Issues Tracker](https://github.com/BarRaider/obs-websocket-dotnet/issues) or discuss in our [Discord](http://discord.barraider.com) ## Dev Discussions **Discord:** Discuss in #developers-chat in [Bar Raiders](http://discord.barraider.com) ## EOL for v4.x branch NOTE: We will no longer be updating the v4.x branch as we move towards v5.0 (which is NOT backwards compatible). ================================================ FILE: TestClient/AdvancedWindow.Designer.cs ================================================ namespace TestClient { partial class AdvancedWindow { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.tbLog = new System.Windows.Forms.TextBox(); this.btnEvents = new System.Windows.Forms.Button(); this.btnSourceFilters = new System.Windows.Forms.Button(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.label2 = new System.Windows.Forms.Label(); this.tbSourceName = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.tbSceneName = new System.Windows.Forms.TextBox(); this.btnInputInfo = new System.Windows.Forms.Button(); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); this.btnSourceInfo = new System.Windows.Forms.Button(); this.btnGetMonitorList = new System.Windows.Forms.Button(); this.btnTransitions = new System.Windows.Forms.Button(); this.btnGetGroupList = new System.Windows.Forms.Button(); this.btnGetInputList = new System.Windows.Forms.Button(); this.btnSourcesList = new System.Windows.Forms.Button(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.btnStopRecord = new System.Windows.Forms.Button(); this.btnRename = new System.Windows.Forms.Button(); this.btnToggleVidCapDvc = new System.Windows.Forms.Button(); this.btnTracks = new System.Windows.Forms.Button(); this.btnCreateScene = new System.Windows.Forms.Button(); this.btnDoNothing = new System.Windows.Forms.Button(); this.groupBox1.SuspendLayout(); this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); this.tabPage2.SuspendLayout(); this.SuspendLayout(); // // tbLog // this.tbLog.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.tbLog.Location = new System.Drawing.Point(12, 80); this.tbLog.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tbLog.Multiline = true; this.tbLog.Name = "tbLog"; this.tbLog.ReadOnly = true; this.tbLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.tbLog.Size = new System.Drawing.Size(874, 600); this.tbLog.TabIndex = 0; // // btnEvents // this.btnEvents.Location = new System.Drawing.Point(896, 20); this.btnEvents.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnEvents.Name = "btnEvents"; this.btnEvents.Size = new System.Drawing.Size(156, 36); this.btnEvents.TabIndex = 1; this.btnEvents.Text = "Events Subscribe"; this.btnEvents.UseVisualStyleBackColor = true; this.btnEvents.Click += new System.EventHandler(this.btnEvents_Click); // // btnSourceFilters // this.btnSourceFilters.Location = new System.Drawing.Point(4, 343); this.btnSourceFilters.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnSourceFilters.Name = "btnSourceFilters"; this.btnSourceFilters.Size = new System.Drawing.Size(149, 36); this.btnSourceFilters.TabIndex = 4; this.btnSourceFilters.Text = "Get Source\'s Filters"; this.btnSourceFilters.UseVisualStyleBackColor = true; this.btnSourceFilters.Click += new System.EventHandler(this.btnSourceFilters_Click); // // groupBox1 // this.groupBox1.Controls.Add(this.label2); this.groupBox1.Controls.Add(this.tbSourceName); this.groupBox1.Controls.Add(this.label1); this.groupBox1.Controls.Add(this.tbSceneName); this.groupBox1.Location = new System.Drawing.Point(12, 12); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(879, 61); this.groupBox1.TabIndex = 13; this.groupBox1.TabStop = false; this.groupBox1.Text = "Inputs (for buttons):"; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(267, 25); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(141, 20); this.label2.TabIndex = 3; this.label2.Text = "Source/Input Name:"; // // tbSourceName // this.tbSourceName.Location = new System.Drawing.Point(414, 25); this.tbSourceName.Name = "tbSourceName"; this.tbSourceName.Size = new System.Drawing.Size(121, 27); this.tbSourceName.TabIndex = 2; // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(7, 25); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(95, 20); this.label1.TabIndex = 1; this.label1.Text = "Scene Name:"; // // tbSceneName // this.tbSceneName.Location = new System.Drawing.Point(107, 25); this.tbSceneName.Name = "tbSceneName"; this.tbSceneName.Size = new System.Drawing.Size(121, 27); this.tbSceneName.TabIndex = 0; // // btnInputInfo // this.btnInputInfo.Location = new System.Drawing.Point(4, 386); this.btnInputInfo.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnInputInfo.Name = "btnInputInfo"; this.btnInputInfo.Size = new System.Drawing.Size(149, 36); this.btnInputInfo.TabIndex = 15; this.btnInputInfo.Text = "Get Input Settings"; this.btnInputInfo.UseVisualStyleBackColor = true; this.btnInputInfo.Click += new System.EventHandler(this.btnInputInfo_Click); // // tabControl1 // this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Location = new System.Drawing.Point(897, 63); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; this.tabControl1.Size = new System.Drawing.Size(162, 621); this.tabControl1.TabIndex = 17; // // tabPage1 // this.tabPage1.Controls.Add(this.btnDoNothing); this.tabPage1.Controls.Add(this.btnSourceInfo); this.tabPage1.Controls.Add(this.btnGetMonitorList); this.tabPage1.Controls.Add(this.btnInputInfo); this.tabPage1.Controls.Add(this.btnTransitions); this.tabPage1.Controls.Add(this.btnGetGroupList); this.tabPage1.Controls.Add(this.btnGetInputList); this.tabPage1.Controls.Add(this.btnSourcesList); this.tabPage1.Controls.Add(this.btnSourceFilters); this.tabPage1.Location = new System.Drawing.Point(4, 29); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(3); this.tabPage1.Size = new System.Drawing.Size(154, 588); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "1"; this.tabPage1.UseVisualStyleBackColor = true; // // btnSourceInfo // this.btnSourceInfo.Location = new System.Drawing.Point(4, 300); this.btnSourceInfo.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnSourceInfo.Name = "btnSourceInfo"; this.btnSourceInfo.Size = new System.Drawing.Size(149, 36); this.btnSourceInfo.TabIndex = 21; this.btnSourceInfo.Text = "Get Source Info"; this.btnSourceInfo.UseVisualStyleBackColor = true; this.btnSourceInfo.Click += new System.EventHandler(this.btnSourceInfo_Click); // // btnGetMonitorList // this.btnGetMonitorList.Location = new System.Drawing.Point(4, 139); this.btnGetMonitorList.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnGetMonitorList.Name = "btnGetMonitorList"; this.btnGetMonitorList.Size = new System.Drawing.Size(149, 36); this.btnGetMonitorList.TabIndex = 19; this.btnGetMonitorList.Text = "List Monitors"; this.btnGetMonitorList.UseVisualStyleBackColor = true; this.btnGetMonitorList.Click += new System.EventHandler(this.btnGetMonitorList_Click); // // btnTransitions // this.btnTransitions.Location = new System.Drawing.Point(4, 183); this.btnTransitions.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnTransitions.Name = "btnTransitions"; this.btnTransitions.Size = new System.Drawing.Size(149, 36); this.btnTransitions.TabIndex = 18; this.btnTransitions.Text = "List Transitions"; this.btnTransitions.UseVisualStyleBackColor = true; this.btnTransitions.Click += new System.EventHandler(this.btnTransition_Click); // // btnGetGroupList // this.btnGetGroupList.Location = new System.Drawing.Point(4, 95); this.btnGetGroupList.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnGetGroupList.Name = "btnGetGroupList"; this.btnGetGroupList.Size = new System.Drawing.Size(149, 36); this.btnGetGroupList.TabIndex = 17; this.btnGetGroupList.Text = "List Groups"; this.btnGetGroupList.UseVisualStyleBackColor = true; this.btnGetGroupList.Click += new System.EventHandler(this.btnGetGroupList_Click); // // btnGetInputList // this.btnGetInputList.Location = new System.Drawing.Point(4, 51); this.btnGetInputList.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnGetInputList.Name = "btnGetInputList"; this.btnGetInputList.Size = new System.Drawing.Size(149, 36); this.btnGetInputList.TabIndex = 16; this.btnGetInputList.Text = "List Inputs"; this.btnGetInputList.UseVisualStyleBackColor = true; this.btnGetInputList.Click += new System.EventHandler(this.btnGetInputList_Click); // // btnSourcesList // this.btnSourcesList.Location = new System.Drawing.Point(4, 7); this.btnSourcesList.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnSourcesList.Name = "btnSourcesList"; this.btnSourcesList.Size = new System.Drawing.Size(149, 36); this.btnSourcesList.TabIndex = 15; this.btnSourcesList.Text = "List Sources"; this.btnSourcesList.UseVisualStyleBackColor = true; this.btnSourcesList.Click += new System.EventHandler(this.btnSourcesList_Click); // // tabPage2 // this.tabPage2.Controls.Add(this.btnStopRecord); this.tabPage2.Controls.Add(this.btnRename); this.tabPage2.Controls.Add(this.btnToggleVidCapDvc); this.tabPage2.Controls.Add(this.btnTracks); this.tabPage2.Controls.Add(this.btnCreateScene); this.tabPage2.Location = new System.Drawing.Point(4, 29); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); this.tabPage2.Size = new System.Drawing.Size(154, 588); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "2"; this.tabPage2.UseVisualStyleBackColor = true; // // btnStopRecord // this.btnStopRecord.Location = new System.Drawing.Point(2, 230); this.btnStopRecord.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.btnStopRecord.Name = "btnStopRecord"; this.btnStopRecord.Size = new System.Drawing.Size(149, 36); this.btnStopRecord.TabIndex = 25; this.btnStopRecord.Text = "Stop Record"; this.btnStopRecord.UseVisualStyleBackColor = true; this.btnStopRecord.Click += new System.EventHandler(this.btnStopRecord_Click); // // btnRename // this.btnRename.Location = new System.Drawing.Point(2, 51); this.btnRename.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnRename.Name = "btnRename"; this.btnRename.Size = new System.Drawing.Size(149, 36); this.btnRename.TabIndex = 24; this.btnRename.Text = "Source Rename"; this.btnRename.UseVisualStyleBackColor = true; // // btnToggleVidCapDvc // this.btnToggleVidCapDvc.Location = new System.Drawing.Point(2, 186); this.btnToggleVidCapDvc.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.btnToggleVidCapDvc.Name = "btnToggleVidCapDvc"; this.btnToggleVidCapDvc.Size = new System.Drawing.Size(149, 36); this.btnToggleVidCapDvc.TabIndex = 23; this.btnToggleVidCapDvc.Text = "Toggle VidCapDvc"; this.btnToggleVidCapDvc.UseVisualStyleBackColor = true; this.btnToggleVidCapDvc.Click += new System.EventHandler(this.btnToggleVidCapDvc_Click); // // btnTracks // this.btnTracks.Location = new System.Drawing.Point(2, 141); this.btnTracks.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnTracks.Name = "btnTracks"; this.btnTracks.Size = new System.Drawing.Size(149, 36); this.btnTracks.TabIndex = 22; this.btnTracks.Text = "Tracks"; this.btnTracks.UseVisualStyleBackColor = true; this.btnTracks.Click += new System.EventHandler(this.btnTracks_Click); // // btnCreateScene // this.btnCreateScene.Location = new System.Drawing.Point(2, 7); this.btnCreateScene.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnCreateScene.Name = "btnCreateScene"; this.btnCreateScene.Size = new System.Drawing.Size(149, 36); this.btnCreateScene.TabIndex = 21; this.btnCreateScene.Text = "Create Scene"; this.btnCreateScene.UseVisualStyleBackColor = true; this.btnCreateScene.Click += new System.EventHandler(this.btnCreateScene_Click); // // btnDoNothing // this.btnDoNothing.Location = new System.Drawing.Point(2, 545); this.btnDoNothing.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnDoNothing.Name = "btnDoNothing"; this.btnDoNothing.Size = new System.Drawing.Size(149, 36); this.btnDoNothing.TabIndex = 22; this.btnDoNothing.Text = "Do Nothing"; this.btnDoNothing.UseVisualStyleBackColor = true; this.btnDoNothing.Click += new System.EventHandler(this.btnDoNothing_Click); // // AdvancedWindow // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1111, 692); this.Controls.Add(this.tabControl1); this.Controls.Add(this.groupBox1); this.Controls.Add(this.btnEvents); this.Controls.Add(this.tbLog); this.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "AdvancedWindow"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "AdvancedWindow"; this.Load += new System.EventHandler(this.AdvancedWindow_Load); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); this.tabControl1.ResumeLayout(false); this.tabPage1.ResumeLayout(false); this.tabPage2.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.TextBox tbLog; private System.Windows.Forms.Button btnEvents; private System.Windows.Forms.Button btnSourceFilters; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.TextBox tbSceneName; private System.Windows.Forms.Label label2; private System.Windows.Forms.TextBox tbSourceName; private System.Windows.Forms.Label label1; private System.Windows.Forms.Button btnInputInfo; private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.Button btnTransitions; private System.Windows.Forms.Button btnGetGroupList; private System.Windows.Forms.Button btnGetInputList; private System.Windows.Forms.Button btnSourcesList; private System.Windows.Forms.Button btnSourceInfo; private System.Windows.Forms.Button btnGetMonitorList; private System.Windows.Forms.Button btnToggleVidCapDvc; private System.Windows.Forms.Button btnTracks; private System.Windows.Forms.Button btnCreateScene; private System.Windows.Forms.Button btnRename; private System.Windows.Forms.Button btnStopRecord; private System.Windows.Forms.Button btnDoNothing; } } ================================================ FILE: TestClient/AdvancedWindow.cs ================================================ using Newtonsoft.Json.Linq; using OBSWebsocketDotNet; using OBSWebsocketDotNet.Types; using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using OBSWebsocketDotNet.Types.Events; namespace TestClient { public partial class AdvancedWindow : Form { #pragma warning disable IDE1006 // Naming Styles // Source to test on private readonly Random random = new Random(); protected OBSWebsocket obs; public void SetOBS(OBSWebsocket obs) { this.obs = obs; } public AdvancedWindow() { InitializeComponent(); } private void AdvancedWindow_Load(object sender, EventArgs e) { } private void btnEvents_Click(object sender, EventArgs e) { if (obs == null) { LogMessage("Error: OBS is null!"); return; } obs.StreamStateChanged += Obs_StreamStateChanged; obs.RecordStateChanged += Obs_RecordStateChanged; obs.Disconnected += Obs_Disconnected; obs.CurrentProgramSceneChanged += Obs_CurrentProgramSceneChanged; obs.CurrentPreviewSceneChanged += Obs_CurrentPreviewSceneChanged; obs.CurrentSceneCollectionChanged += Obs_CurrentSceneCollectionChanged; obs.CurrentSceneTransitionChanged += Obs_CurrentSceneTransitionChanged; obs.CurrentSceneTransitionDurationChanged += Obs_CurrentSceneTransitionDurationChanged; obs.CurrentProfileChanged += Obs_CurrentProfileChanged; obs.InputActiveStateChanged += Obs_InputActiveStateChanged; obs.InputMuteStateChanged += Obs_InputMuteStateChanged; obs.InputVolumeChanged += OBS_onInputVolumeChanged; obs.ProfileListChanged += Obs_ProfileListChanged; obs.ReplayBufferStateChanged += Obs_ReplayBufferStateChanged; obs.ReplayBufferSaved += Obs_ReplayBufferSaved; obs.SceneCollectionListChanged += Obs_SceneCollectionListChanged; obs.SceneItemCreated += Obs_SceneItemCreated; obs.SceneItemRemoved += Obs_SceneItemRemoved; obs.SceneItemSelected += Obs_SceneItemSelected; obs.SceneItemLockStateChanged += OBS_onSceneItemLockStateChanged; obs.SceneItemEnableStateChanged += OBS_onSceneItemEnableStateChanged; obs.SceneItemTransformChanged += Obs_SceneItemTransformChanged; obs.SceneItemListReindexed += OBS_onSceneItemListIndexingChanged; obs.SceneListChanged += Obs_SceneListChanged; obs.SceneTransitionStarted += OBS_onSceneTransitionStarted; obs.SceneTransitionEnded += OBS_onSceneTransitionEnded; obs.SceneTransitionVideoEnded += OBS_onSceneTransitionVideoEnded; obs.SourceFilterCreated += OBS_onSourceFilterCreated; obs.SourceFilterEnableStateChanged += OBS_onSourceFilterEnableStateChanged; obs.SourceFilterRemoved += OBS_onSourceFilterRemoved; obs.SourceFilterListReindexed += OBS_onSourceFilterListReindexed; obs.StudioModeStateChanged += Obs_StudioModeStateChanged; obs.VirtualcamStateChanged += Obs_VirtualcamStateChanged; } private void Obs_InputActiveStateChanged(object sender, InputActiveStateChangedEventArgs args) { LogMessage($"[InputActiveStateChanged] Name: {args.InputName} Video Active: {args.VideoActive}"); } private void Obs_InputMuteStateChanged(object sender, InputMuteStateChangedEventArgs args) { LogMessage($"[InputMuteStateChanged] Name: {args.InputName} Muted: {args.InputMuted}"); } private void Obs_SceneItemTransformChanged(object sender, SceneItemTransformEventArgs args) { LogMessage($"[SceneItemTransformChanged] Scene: {args.SceneName} ItemId: {args.SceneItemId} Transform: {args.Transform.X},{args.Transform.Y}"); } private void Obs_SceneItemSelected(object sender, SceneItemSelectedEventArgs args) { LogMessage($"[SceneItemSelected] Scene: {args.SceneName} ItemId: {args.SceneItemId}"); } private void Obs_Disconnected(object sender, OBSWebsocketDotNet.Communication.ObsDisconnectionInfo e) { LogMessage($"[OBS DISCONNECTED] CloseCode: {e.ObsCloseCode} Reason: {e.DisconnectReason} Type: {e.WebsocketDisconnectionInfo?.Type} Exception: {e.WebsocketDisconnectionInfo?.Exception?.Message}"); } private void Obs_StudioModeStateChanged(object sender, StudioModeStateChangedEventArgs args) { LogMessage($"[Preview/Studio ModeChanged] Enabled: {args.StudioModeEnabled}"); } private void Obs_ReplayBufferSaved(object sender, ReplayBufferSavedEventArgs args) { LogMessage($"[ReplayBufferSaved] Save Location: {args.SavedReplayPath}"); } private void Obs_ReplayBufferStateChanged(object sender, ReplayBufferStateChangedEventArgs args) { LogMessage($"[ReplayBufferStateChanged] Active: {args.OutputState.IsActive} State: {args.OutputState.StateStr} {args.OutputState.State}"); } private void Obs_RecordStateChanged(object sender, RecordStateChangedEventArgs args) { LogMessage($"[RecordingStateChanged] Active: {args.OutputState.IsActive} Output: {args.OutputState.OutputPath} State: {args.OutputState.StateStr} {args.OutputState.State}"); } private void Obs_StreamStateChanged(object sender, StreamStateChangedEventArgs args) { LogMessage($"[StreamStateChanged] Active: {args.OutputState.IsActive} State: {args.OutputState.StateStr} {args.OutputState.State}"); } private void Obs_VirtualcamStateChanged(object sender, VirtualcamStateChangedEventArgs args) { LogMessage($"[VirtualcamStateChanged] Active: {args.OutputState.IsActive} State: {args.OutputState.StateStr} {args.OutputState.State}"); } private void Obs_ProfileListChanged(object sender, ProfileListChangedEventArgs args) { LogMessage($"[ProfileListchanged] Count: {args.Profiles.Count}"); foreach (var profile in args.Profiles) { LogMessage($"\t{profile}"); } } private void Obs_CurrentProfileChanged(object sender, CurrentProfileChangedEventArgs args) { LogMessage($"[CurrentProfileChanged] Current: {args.ProfileName}"); } private void Obs_CurrentSceneTransitionDurationChanged(object sender, CurrentSceneTransitionDurationChangedEventArgs args) { LogMessage($"[CurrentSceneTransitionDurationChanged] Current: {args.TransitionDuration}"); } private void Obs_CurrentSceneTransitionChanged(object sender, CurrentSceneTransitionChangedEventArgs args) { LogMessage($"[CurrentSceneTransitionChanged] Current: {args.TransitionName}"); } private void Obs_SceneCollectionListChanged(object sender, SceneCollectionListChangedEventArgs args) { LogMessage($"[SceneCollectionListChanged] Count: {args.SceneCollections.Count}"); foreach (var sc in args.SceneCollections) { LogMessage($"\t{sc}"); } } private void Obs_CurrentSceneCollectionChanged(object sender, CurrentSceneCollectionChangedEventArgs args) { LogMessage($"[CurrentSceneCollectionChanged] Current: {args.SceneCollectionName}"); } private void Obs_SceneItemRemoved(object sender, SceneItemRemovedEventArgs args) { LogMessage($"[SceneItemRemoved] Scene: {args.SourceName} Source: {args.SourceName} ItemId: {args.SceneItemId}"); } private void Obs_SceneItemCreated(object sender, SceneItemCreatedEventArgs args) { LogMessage($"[SceneItemCreated] Scene: {args.SourceName} Source: {args.SourceName} ItemId: {args.SceneItemId} ItemIndex: {args.SceneItemIndex}"); } private void Obs_SceneListChanged(object sender, SceneListChangedEventArgs args) { LogMessage($"[SceneListChanged] Count: {args.Scenes.Count}"); foreach (var scene in args.Scenes) { LogMessage($"\n{scene}"); } } private void Obs_CurrentProgramSceneChanged(object sender, ProgramSceneChangedEventArgs args) { LogMessage($"[SceneChanged] Current: {args.SceneName}"); } private void Obs_CurrentPreviewSceneChanged(object sender, CurrentPreviewSceneChangedEventArgs args) { LogMessage($"[Preview/Studio SceneChanged] Current: {args.SceneName}"); } private void OBS_onInputVolumeChanged(object sender, InputVolumeChangedEventArgs args) { LogMessage($"[SourceVolumeChanged] Source: {args.Volume.InputName} Volume: {args.Volume.InputVolumeMul} VolumeDB: {args.Volume.InputVolumeDb}"); } private void OBS_onSceneItemEnableStateChanged(object sender, SceneItemEnableStateChangedEventArgs args) { LogMessage($"[SceneItemEnableStateChanged] Scene: {args.SceneName} ItemId: {args.SceneItemId} Enabled?: {args.SceneItemEnabled}"); } private void OBS_onSceneItemLockStateChanged(object sender, SceneItemLockStateChangedEventArgs args) { LogMessage($"[SceneItemLockStateChanged] Scene: {args.SceneName} ItemId: {args.SceneItemId} IsLocked: {args.SceneItemLocked}"); } private void OBS_onSourceFilterListReindexed(object sender, SourceFilterListReindexedEventArgs args) { LogMessage($"[SourceFilterListReindexed] Source: {args.SourceName}"); foreach (var filter in args.Filters) { LogMessage($"\t{filter.Name}"); } } private void OBS_onSceneItemListIndexingChanged(object sender, SceneItemListReindexedEventArgs args) { LogMessage($"[SceneItemListReindexed] Scene: {args.SceneName}{Environment.NewLine}\tSceneItems: {args.SceneItems}"); } private void OBS_onSourceFilterEnableStateChanged(object sender, SourceFilterEnableStateChangedEventArgs args) { LogMessage($"[SourceFilterEnableStateChanged] Source: {args.SourceName} Filter: {args.FilterName} Enabled: {args.FilterEnabled}"); } private void OBS_onSourceFilterRemoved(object sender, SourceFilterRemovedEventArgs args) { LogMessage($"[SourceFilterRemoved] Source: {args.SourceName} Filter: {args.FilterName}"); } private void OBS_onSourceFilterCreated(object sender, SourceFilterCreatedEventArgs args) { LogMessage($"[SourceFilterCreated] Source: {args.SourceName} Filter: {args.FilterName} FilterKind: {args.FilterKind} FilterIndex: {args.FilterIndex}{Environment.NewLine}\tSettings: {args.FilterSettings}{Environment.NewLine}\tDefaultSettings: {args.DefaultFilterSettings}"); } private void OBS_onSceneTransitionVideoEnded(object sender, SceneTransitionVideoEndedEventArgs args) { LogMessage($"[SceneTransitionVideoEnded] Name: {args.TransitionName}"); } private void OBS_onSceneTransitionEnded(object sender, SceneTransitionEndedEventArgs args) { LogMessage($"[SceneTransitionEnded] Name: {args.TransitionName}"); } private void OBS_onSceneTransitionStarted(object sender, SceneTransitionStartedEventArgs args) { LogMessage($"[SceneTransitionStarted] Name: {args.TransitionName}"); } private void LogMessage(string message) { if (InvokeRequired) { this.Invoke(new MethodInvoker(() => { tbLog.AppendText($"{Environment.NewLine}[{DateTime.Now:HH:mm:ss}]{message}"); })); } else { tbLog.AppendText($"{Environment.NewLine}[{DateTime.Now:HH:mm:ss}]{message}"); } } private void btnRename_Click(object sender, EventArgs e) { if (String.IsNullOrEmpty(tbSourceName.Text)) { MessageBox.Show("Enter name of Source in input box"); return; } string source = tbSourceName.Text; var active = obs.GetSourceActive(source).VideoActive; LogMessage($"GetSourceActive for {source}: {active}. Renaming source"); obs.SetInputName(source, source + random.Next(100)); } private void btnSourceInfo_Click(object sender, EventArgs e) { if (String.IsNullOrEmpty(tbSceneName.Text)) { MessageBox.Show("Enter name of Scene in input box"); return; } if (String.IsNullOrEmpty(tbSourceName.Text)) { MessageBox.Show("Enter name of Source in input box"); return; } string scene = tbSceneName.Text; string source = tbSourceName.Text; int itemId = obs.GetSceneItemId(scene, source, 0); LogMessage($"Item Id for {source} is {itemId}"); bool isEnabled = obs.GetSceneItemEnabled(scene, itemId); LogMessage($"Source Enabled: {isEnabled}"); bool isLocked = obs.GetSceneItemLocked(scene, itemId); LogMessage($"Source Locked: {isLocked}"); JObject data = obs.GetSceneItemTransformRaw(scene, itemId); LogMessage($"Raw Data: {data}"); var transform = obs.GetSceneItemTransform(scene, itemId); LogMessage($"Transform Object: X: {transform.X}, Y: {transform.Y}, ScaleX: {transform.ScaleX}, ScaleY: {transform.ScaleY}, Height: {transform.Height}, Width: {transform.Width}, SourceHeight: {transform.SourceHeight}, SourceWidth: {transform.SourceWidth}, Rotation: {transform.Rotation}, Crop Top: {transform.CropTop}, Crop Bottom: {transform.CropBottom}, Crop Left: {transform.CropLeft}, Crop Right: {transform.CropRight}"); LogMessage($"Alignment: {transform.Alignnment}, BoundsHeight: {transform.BoundsHeight}, BoundsWidth: {transform.BoundsWidth}, BoundsType: {transform.BoundsType}"); } private void btnSourceFilters_Click(object sender, EventArgs e) { try { if (String.IsNullOrEmpty(tbSourceName.Text)) { MessageBox.Show("Enter name of Source in input box"); return; } string source = tbSourceName.Text; LogMessage("GetSourceFilters:"); var filters = obs.GetSourceFilterList(source); foreach (var filter in filters) { LogFilter(filter); } var firstFilter = filters.FirstOrDefault(); if (firstFilter == null) { LogMessage("ERROR: No filters found"); return; } LogMessage("GetSourceFilterInfo:"); LogFilter(obs.GetSourceFilter(source, firstFilter.Name)); } catch (Exception ex) { LogMessage($"ERROR: {ex}"); } } private void LogFilter(FilterSettings filter) { LogMessage($"Filter: {filter.Name} Type: {filter.Kind} Enabled: {filter.IsEnabled}{Environment.NewLine}Settings: {filter.Settings}"); } private void btnCreateScene_Click(object sender, EventArgs e) { if (String.IsNullOrEmpty(tbSceneName.Text)) { MessageBox.Show("Enter name of Scene in input box"); return; } string newScene = tbSceneName.Text; obs.CreateScene(newScene); var createdScene = obs.GetSceneList().Scenes.FirstOrDefault(s => s.Name == newScene); if (createdScene == null) { LogMessage($"ERROR: Scene was not created!"); return; } LogMessage($"Created scene: {createdScene.Name}"); } private void btnOutputs_Click(object sender, EventArgs e) { // TODO refactor for v5.0.0 if possible /*LogMessage("Testing ListOutputs:"); var outputs = obs.ListOutputs(); foreach (var output in outputs) { LogOutput(output); } LogMessage("Testing GetOutputInfo:"); var firstOutput = outputs.Skip(1).FirstOrDefault(); if (firstOutput == null) { LogMessage($"ERROR: No outputs retrieved!"); return; }*/ // TODO: Reuse when properly works on Windows /* Output information does not work properly on OBS Websocket Window string outputName = firstOutput.Name; var retrievedOutput = obs.GetOutputInfo(outputName); LogOutput(retrievedOutput); LogMessage("Testing StartOutput:"); obs.StartOutput(outputName); retrievedOutput = obs.GetOutputInfo(outputName); LogOutput(retrievedOutput); LogMessage("Testing StopOutput:"); obs.StopOutput(outputName); retrievedOutput = obs.GetOutputInfo(outputName); LogOutput(retrievedOutput); */ } private void btnTransition_Click(object sender, EventArgs e) { LogMessage($"Getting Transitions"); var transitions = obs.GetSceneTransitionList(); LogMessage($"Found {transitions.Transitions.Count} transitions. Active: {transitions.CurrentTransition}"); var enteringTransition = obs.GetCurrentSceneTransition(); foreach (var transition in transitions.Transitions) { obs.SetCurrentSceneTransition(transition.Name); var activeTransition = obs.GetCurrentSceneTransition(); var info = activeTransition.Settings; info ??= new JObject(); LogMessage($"Transition: {transition.Name} has {info.Count} settings"); } obs.SetCurrentSceneTransition(enteringTransition.Name); } private void btnTracks_Click(object sender, EventArgs e) { try { if (String.IsNullOrEmpty(tbSourceName.Text)) { MessageBox.Show("Enter name of Source in input box"); return; } string source = tbSourceName.Text; LogMessage($"Getting tracks for source {source}:"); var tracks = obs.GetInputAudioTracks(source); if (tracks == null) { LogMessage("ERROR: No tracks returned"); return; } LogMessage($"Active Tracks: 1 {tracks.IsTrack1Active}, 2 {tracks.IsTrack2Active}, 3 {tracks.IsTrack3Active}, 4 {tracks.IsTrack4Active}, 5 {tracks.IsTrack5Active}, 6 {tracks.IsTrack6Active}"); bool trackToggle = !tracks.IsTrack3Active; LogMessage($"Setting Track 3 to {trackToggle}"); // TODO: Get track settings structure to set track values appropriately //obs.SetInputAudioTracks(SOURCE_NAME, 3, trackToggle); tracks = obs.GetInputAudioTracks(source); LogMessage($"Active Tracks: 1 {tracks.IsTrack1Active}, 2 {tracks.IsTrack2Active}, 3 {tracks.IsTrack3Active}, 4 {tracks.IsTrack4Active}, 5 {tracks.IsTrack5Active}, 6 {tracks.IsTrack6Active}"); LogMessage($"Value is {tracks.IsTrack3Active} expected {trackToggle}"); if (tracks.IsTrack3Active != trackToggle) { LogMessage("ERROR: FAILED!"); return; } trackToggle = !tracks.IsTrack3Active; LogMessage($"Setting Track 3 back to to {trackToggle}"); // TODO: Get track settings structure to set track values appropriately //obs.SetInputAudioTracks(SOURCE_NAME, 3, trackToggle); tracks = obs.GetInputAudioTracks(source); LogMessage($"Active Tracks: 1 {tracks.IsTrack1Active}, 2 {tracks.IsTrack2Active}, 3 {tracks.IsTrack3Active}, 4 {tracks.IsTrack4Active}, 5 {tracks.IsTrack5Active}, 6 {tracks.IsTrack6Active}"); LogMessage($"Value is {tracks.IsTrack3Active} expected {trackToggle}"); if (tracks.IsTrack3Active != trackToggle) { LogMessage("ERROR: FAILED!"); return; } } catch (Exception ex) { LogMessage($"ERROR: {ex}"); } } private void btnToggleVidCapDvc_Click(object sender, EventArgs e) { var sceneName = obs.GetCurrentProgramScene(); var sourceItems = obs.GetSceneItemList(sceneName); var vidCapItems = sourceItems.Where(x => x.SourceKind.Equals("dshow_input")); var itemListSettings = new List(); foreach (var vidCapItem in vidCapItems) { var enabled = obs.GetSceneItemEnabled(sceneName, vidCapItem.ItemId); obs.SetSceneItemEnabled(sceneName, vidCapItem.ItemId, enabled ? false : true); LogMessage($"{vidCapItem.SourceName} active button toggled."); } } private void btnGetInputList_Click(object sender, EventArgs e) { LogMessage("Getting OBS Input List..."); var inputList = obs.GetInputList(); foreach (var input in inputList) { LogMessage($"{input.InputName} {input.InputKind} {input.UnversionedKind}"); } LogMessage("Getting Input Kind list"); var inputKinds = obs.GetInputKindList(); foreach (var kind in inputKinds) { LogMessage($"{kind}\n"); } } private void btnGetGroupList_Click(object sender, EventArgs e) { LogMessage("Getting Group Item List..."); var groupItems = obs.GetGroupList(); foreach (var groupItem in groupItems) { LogMessage(groupItem.ToString()); } } private void btnGetMonitorList_Click(object sender, EventArgs e) { LogMessage("Getting Monitor List..."); var monitorList = obs.GetMonitorList(); foreach (var monitor in monitorList) { LogMessage($"{monitor.Index} {monitor.Name} {monitor.Width}x{monitor.Height} {monitor.PositionX},{monitor.PositionY}"); } } private void btnInputInfo_Click(object sender, EventArgs e) { if (String.IsNullOrEmpty(tbSourceName.Text)) { MessageBox.Show("Enter name of Input in input box"); return; } string input = tbSourceName.Text; var inputSettings = obs.GetInputSettings(input); LogMessage($"Name: {inputSettings.InputName} Kind: {inputSettings.InputKind} \r\nSettings: {inputSettings.Settings}"); var defaults = obs.GetInputDefaultSettings(inputSettings.InputKind); LogMessage($"*** Defaults for {inputSettings.InputKind} ***:\r\n {defaults}"); } private void btnSourcesList_Click(object sender, EventArgs e) { var scenes = obs.GetSceneList(); foreach (var scene in scenes.Scenes) { LogMessage($"Scene: {scene.Name} Index: {scene.Index}"); var sources = obs.GetSceneItemList(scene.Name); LogMessage($"\t Total Items: {sources.Count} \tItems' Names: {String.Join(',', sources.Select(i => i.SourceName).ToArray())}"); } } private void btnStopRecord_Click(object sender, EventArgs e) { string output = obs.StopRecord(); LogMessage($"Stop record: Output is {output}"); } private void btnDoNothing_Click(object sender, EventArgs e) { } #pragma warning restore IDE1006 // Naming Styles } } ================================================ FILE: TestClient/AdvancedWindow.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: TestClient/App.config ================================================ ================================================ FILE: TestClient/LICENSE.md ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: TestClient/MainWindow.Designer.cs ================================================ /* TestClient for obs-websocket-dotnet Copyright (C) 2021 Stéphane Lepin, BarRaider This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see */ namespace TestClient { partial class MainWindow { /// /// Variable nécessaire au concepteur. /// private System.ComponentModel.IContainer components = null; /// /// Nettoyage des ressources utilisées. /// /// true si les ressources managées doivent être supprimées ; sinon, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Code généré par le Concepteur Windows Form /// /// Méthode requise pour la prise en charge du concepteur - ne modifiez pas /// le contenu de cette méthode avec l'éditeur de code. /// private void InitializeComponent() { this.btnConnect = new System.Windows.Forms.Button(); this.txtServerIP = new System.Windows.Forms.TextBox(); this.txtServerPassword = new System.Windows.Forms.TextBox(); this.tvScenes = new System.Windows.Forms.TreeView(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.btnSetCurrentScene = new System.Windows.Forms.Button(); this.btnGetCurrentScene = new System.Windows.Forms.Button(); this.btnListScenes = new System.Windows.Forms.Button(); this.tbCurrentScene = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.gbControls = new System.Windows.Forms.GroupBox(); this.groupBox9 = new System.Windows.Forms.GroupBox(); this.lblVirtualCamStatus = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label(); this.btnVirtualCamToggle = new System.Windows.Forms.Button(); this.btnVirtualCamStop = new System.Windows.Forms.Button(); this.btnVirtualCamStart = new System.Windows.Forms.Button(); this.groupBox8 = new System.Windows.Forms.GroupBox(); this.btnBrowse = new System.Windows.Forms.Button(); this.tbFolderPath = new System.Windows.Forms.TextBox(); this.btnSetPath = new System.Windows.Forms.Button(); this.btnAdvanced = new System.Windows.Forms.Button(); this.groupBox7 = new System.Windows.Forms.GroupBox(); this.btnSetTransitionDuration = new System.Windows.Forms.Button(); this.btnGetTransitionDuration = new System.Windows.Forms.Button(); this.tbTransitionDuration = new System.Windows.Forms.NumericUpDown(); this.groupBox6 = new System.Windows.Forms.GroupBox(); this.btnSetCurrentTransition = new System.Windows.Forms.Button(); this.btnGetCurrentTransition = new System.Windows.Forms.Button(); this.tbTransition = new System.Windows.Forms.TextBox(); this.btnListTransitions = new System.Windows.Forms.Button(); this.tvTransitions = new System.Windows.Forms.TreeView(); this.gbStatus = new System.Windows.Forms.GroupBox(); this.tabStats = new System.Windows.Forms.TabControl(); this.obsPage = new System.Windows.Forms.TabPage(); this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); this.lblOutgoingMessages = new System.Windows.Forms.Label(); this.lblIncomingMessages = new System.Windows.Forms.Label(); this.lblDisk = new System.Windows.Forms.Label(); this.lblMemory = new System.Windows.Forms.Label(); this.lblCPU = new System.Windows.Forms.Label(); this.lblFPS = new System.Windows.Forms.Label(); this.lblAvgRender = new System.Windows.Forms.Label(); this.lblSkipped = new System.Windows.Forms.Label(); this.label26 = new System.Windows.Forms.Label(); this.label25 = new System.Windows.Forms.Label(); this.label24 = new System.Windows.Forms.Label(); this.label23 = new System.Windows.Forms.Label(); this.label22 = new System.Windows.Forms.Label(); this.lblOutputTotal = new System.Windows.Forms.Label(); this.label20 = new System.Windows.Forms.Label(); this.label19 = new System.Windows.Forms.Label(); this.label18 = new System.Windows.Forms.Label(); this.label17 = new System.Windows.Forms.Label(); this.label16 = new System.Windows.Forms.Label(); this.label15 = new System.Windows.Forms.Label(); this.lblMissed = new System.Windows.Forms.Label(); this.lblRendered = new System.Windows.Forms.Label(); this.streamPage = new System.Windows.Forms.TabPage(); this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); this.lblStreamSkippedFrames = new System.Windows.Forms.Label(); this.label32 = new System.Windows.Forms.Label(); this.label31 = new System.Windows.Forms.Label(); this.lblStreamOutputBytes = new System.Windows.Forms.Label(); this.lblStreamTotalFrames = new System.Windows.Forms.Label(); this.lblStreamCongestion = new System.Windows.Forms.Label(); this.lblStreamDuration = new System.Windows.Forms.Label(); this.lblStreamTimeCode = new System.Windows.Forms.Label(); this.lblStreamReconnect = new System.Windows.Forms.Label(); this.lblStreamActive = new System.Windows.Forms.Label(); this.label6 = new System.Windows.Forms.Label(); this.label7 = new System.Windows.Forms.Label(); this.label8 = new System.Windows.Forms.Label(); this.label9 = new System.Windows.Forms.Label(); this.label10 = new System.Windows.Forms.Label(); this.label11 = new System.Windows.Forms.Label(); this.recPage = new System.Windows.Forms.TabPage(); this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel(); this.lblRecordingBytes = new System.Windows.Forms.Label(); this.lblRecordingDuration = new System.Windows.Forms.Label(); this.lblRecordingTimeCode = new System.Windows.Forms.Label(); this.lblRecordingPaused = new System.Windows.Forms.Label(); this.lblRecording = new System.Windows.Forms.Label(); this.label30 = new System.Windows.Forms.Label(); this.label29 = new System.Windows.Forms.Label(); this.label28 = new System.Windows.Forms.Label(); this.label27 = new System.Windows.Forms.Label(); this.label21 = new System.Windows.Forms.Label(); this.groupBox5 = new System.Windows.Forms.GroupBox(); this.btnPauseRecording = new System.Windows.Forms.Button(); this.btnToggleRecording = new System.Windows.Forms.Button(); this.btnToggleStreaming = new System.Windows.Forms.Button(); this.groupBox4 = new System.Windows.Forms.GroupBox(); this.btnSetCurrentProfile = new System.Windows.Forms.Button(); this.btnGetCurrentProfile = new System.Windows.Forms.Button(); this.tbProfile = new System.Windows.Forms.TextBox(); this.btnListProfiles = new System.Windows.Forms.Button(); this.tvProfiles = new System.Windows.Forms.TreeView(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.btnSetCurrentSceneCol = new System.Windows.Forms.Button(); this.btnGetCurrentSceneCol = new System.Windows.Forms.Button(); this.tbSceneCol = new System.Windows.Forms.TextBox(); this.btnListSceneCol = new System.Windows.Forms.Button(); this.tvSceneCols = new System.Windows.Forms.TreeView(); this.groupBox3 = new System.Windows.Forms.GroupBox(); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); this.tbOBSVersion = new System.Windows.Forms.Label(); this.tbPluginVersion = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); this.label5 = new System.Windows.Forms.Label(); this.button3 = new System.Windows.Forms.Button(); this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog(); this.label13 = new System.Windows.Forms.Label(); this.label14 = new System.Windows.Forms.Label(); this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); this.fileSystemWatcher1 = new System.IO.FileSystemWatcher(); this.groupBox1.SuspendLayout(); this.gbControls.SuspendLayout(); this.groupBox9.SuspendLayout(); this.groupBox8.SuspendLayout(); this.groupBox7.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.tbTransitionDuration)).BeginInit(); this.groupBox6.SuspendLayout(); this.gbStatus.SuspendLayout(); this.tabStats.SuspendLayout(); this.obsPage.SuspendLayout(); this.tableLayoutPanel3.SuspendLayout(); this.streamPage.SuspendLayout(); this.tableLayoutPanel2.SuspendLayout(); this.recPage.SuspendLayout(); this.tableLayoutPanel5.SuspendLayout(); this.groupBox5.SuspendLayout(); this.groupBox4.SuspendLayout(); this.groupBox2.SuspendLayout(); this.groupBox3.SuspendLayout(); this.tableLayoutPanel1.SuspendLayout(); this.tableLayoutPanel4.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.fileSystemWatcher1)).BeginInit(); this.SuspendLayout(); // // btnConnect // this.btnConnect.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnConnect.Location = new System.Drawing.Point(681, 8); this.btnConnect.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnConnect.Name = "btnConnect"; this.btnConnect.Size = new System.Drawing.Size(101, 36); this.btnConnect.TabIndex = 1; this.btnConnect.Text = "Connect"; this.btnConnect.UseVisualStyleBackColor = true; this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click); // // txtServerIP // this.txtServerIP.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.txtServerIP.Location = new System.Drawing.Point(271, 11); this.txtServerIP.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.txtServerIP.Name = "txtServerIP"; this.txtServerIP.Size = new System.Drawing.Size(150, 27); this.txtServerIP.TabIndex = 2; this.txtServerIP.Text = "ws://127.0.0.1:4455"; // // txtServerPassword // this.txtServerPassword.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.txtServerPassword.Location = new System.Drawing.Point(521, 11); this.txtServerPassword.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.txtServerPassword.Name = "txtServerPassword"; this.txtServerPassword.Size = new System.Drawing.Size(150, 27); this.txtServerPassword.TabIndex = 3; this.txtServerPassword.UseSystemPasswordChar = true; // // tvScenes // this.tvScenes.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tvScenes.Location = new System.Drawing.Point(8, 76); this.tvScenes.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tvScenes.Name = "tvScenes"; this.tvScenes.Size = new System.Drawing.Size(182, 180); this.tvScenes.TabIndex = 4; this.tvScenes.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.tvScenes_NodeMouseClick); // // groupBox1 // this.groupBox1.Controls.Add(this.btnSetCurrentScene); this.groupBox1.Controls.Add(this.btnGetCurrentScene); this.groupBox1.Controls.Add(this.btnListScenes); this.groupBox1.Controls.Add(this.tvScenes); this.groupBox1.Controls.Add(this.tbCurrentScene); this.groupBox1.Location = new System.Drawing.Point(8, 19); this.groupBox1.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox1.Name = "groupBox1"; this.groupBox1.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox1.Size = new System.Drawing.Size(200, 373); this.groupBox1.TabIndex = 5; this.groupBox1.TabStop = false; this.groupBox1.Text = "Scene List with Items"; // // btnSetCurrentScene // this.btnSetCurrentScene.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnSetCurrentScene.Location = new System.Drawing.Point(104, 307); this.btnSetCurrentScene.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnSetCurrentScene.Name = "btnSetCurrentScene"; this.btnSetCurrentScene.Size = new System.Drawing.Size(88, 59); this.btnSetCurrentScene.TabIndex = 1; this.btnSetCurrentScene.Text = "Set\r\nCurScene"; this.btnSetCurrentScene.UseVisualStyleBackColor = true; this.btnSetCurrentScene.Click += new System.EventHandler(this.btnSetCurrentScene_Click); // // btnGetCurrentScene // this.btnGetCurrentScene.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnGetCurrentScene.Location = new System.Drawing.Point(8, 307); this.btnGetCurrentScene.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnGetCurrentScene.Name = "btnGetCurrentScene"; this.btnGetCurrentScene.Size = new System.Drawing.Size(82, 59); this.btnGetCurrentScene.TabIndex = 2; this.btnGetCurrentScene.Text = "Get\r\nCurScene"; this.btnGetCurrentScene.UseVisualStyleBackColor = true; this.btnGetCurrentScene.Click += new System.EventHandler(this.btnGetCurrentScene_Click); // // btnListScenes // this.btnListScenes.Location = new System.Drawing.Point(9, 31); this.btnListScenes.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnListScenes.Name = "btnListScenes"; this.btnListScenes.Size = new System.Drawing.Size(101, 36); this.btnListScenes.TabIndex = 5; this.btnListScenes.Text = "ListScenes"; this.btnListScenes.UseVisualStyleBackColor = true; this.btnListScenes.Click += new System.EventHandler(this.btnListScenes_Click); // // tbCurrentScene // this.tbCurrentScene.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tbCurrentScene.Location = new System.Drawing.Point(8, 267); this.tbCurrentScene.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tbCurrentScene.Name = "tbCurrentScene"; this.tbCurrentScene.Size = new System.Drawing.Size(182, 27); this.tbCurrentScene.TabIndex = 0; // // label1 // this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(192, 16); this.label1.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(66, 20); this.label1.TabIndex = 7; this.label1.Text = "IP:PORT :"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // label2 // this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(440, 16); this.label2.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(77, 20); this.label2.TabIndex = 8; this.label2.Text = "Password :"; // // gbControls // this.gbControls.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.gbControls.Controls.Add(this.groupBox9); this.gbControls.Controls.Add(this.groupBox8); this.gbControls.Controls.Add(this.btnAdvanced); this.gbControls.Controls.Add(this.groupBox7); this.gbControls.Controls.Add(this.groupBox6); this.gbControls.Controls.Add(this.gbStatus); this.gbControls.Controls.Add(this.groupBox5); this.gbControls.Controls.Add(this.groupBox4); this.gbControls.Controls.Add(this.groupBox2); this.gbControls.Controls.Add(this.groupBox3); this.gbControls.Controls.Add(this.groupBox1); this.gbControls.Enabled = false; this.gbControls.Location = new System.Drawing.Point(15, 52); this.gbControls.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.gbControls.Name = "gbControls"; this.gbControls.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); this.gbControls.Size = new System.Drawing.Size(766, 856); this.gbControls.TabIndex = 9; this.gbControls.TabStop = false; // // groupBox9 // this.groupBox9.Controls.Add(this.lblVirtualCamStatus); this.groupBox9.Controls.Add(this.label4); this.groupBox9.Controls.Add(this.btnVirtualCamToggle); this.groupBox9.Controls.Add(this.btnVirtualCamStop); this.groupBox9.Controls.Add(this.btnVirtualCamStart); this.groupBox9.Location = new System.Drawing.Point(562, 571); this.groupBox9.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox9.Name = "groupBox9"; this.groupBox9.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox9.Size = new System.Drawing.Size(194, 89); this.groupBox9.TabIndex = 13; this.groupBox9.TabStop = false; this.groupBox9.Text = "Virtual Cam"; // // lblVirtualCamStatus // this.lblVirtualCamStatus.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblVirtualCamStatus.Location = new System.Drawing.Point(65, 23); this.lblVirtualCamStatus.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblVirtualCamStatus.Name = "lblVirtualCamStatus"; this.lblVirtualCamStatus.Size = new System.Drawing.Size(122, 20); this.lblVirtualCamStatus.TabIndex = 8; this.lblVirtualCamStatus.Text = "Unknown"; this.lblVirtualCamStatus.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label4 // this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label4.AutoSize = true; this.label4.Location = new System.Drawing.Point(7, 23); this.label4.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(52, 20); this.label4.TabIndex = 7; this.label4.Text = "Status:"; this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // btnVirtualCamToggle // this.btnVirtualCamToggle.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnVirtualCamToggle.Location = new System.Drawing.Point(125, 44); this.btnVirtualCamToggle.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnVirtualCamToggle.Name = "btnVirtualCamToggle"; this.btnVirtualCamToggle.Size = new System.Drawing.Size(64, 36); this.btnVirtualCamToggle.TabIndex = 3; this.btnVirtualCamToggle.Text = "Toggle"; this.btnVirtualCamToggle.UseVisualStyleBackColor = true; this.btnVirtualCamToggle.Click += new System.EventHandler(this.btnVirtualCamToggle_Click); // // btnVirtualCamStop // this.btnVirtualCamStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnVirtualCamStop.Location = new System.Drawing.Point(67, 44); this.btnVirtualCamStop.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnVirtualCamStop.Name = "btnVirtualCamStop"; this.btnVirtualCamStop.Size = new System.Drawing.Size(54, 36); this.btnVirtualCamStop.TabIndex = 2; this.btnVirtualCamStop.Text = "Stop"; this.btnVirtualCamStop.UseVisualStyleBackColor = true; this.btnVirtualCamStop.Click += new System.EventHandler(this.btnVirtualCamStop_Click); // // btnVirtualCamStart // this.btnVirtualCamStart.Location = new System.Drawing.Point(7, 44); this.btnVirtualCamStart.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnVirtualCamStart.Name = "btnVirtualCamStart"; this.btnVirtualCamStart.Size = new System.Drawing.Size(55, 36); this.btnVirtualCamStart.TabIndex = 1; this.btnVirtualCamStart.Text = "Start"; this.btnVirtualCamStart.UseVisualStyleBackColor = true; this.btnVirtualCamStart.Click += new System.EventHandler(this.btnVirtualCamStart_Click); // // groupBox8 // this.groupBox8.Controls.Add(this.btnBrowse); this.groupBox8.Controls.Add(this.tbFolderPath); this.groupBox8.Controls.Add(this.btnSetPath); this.groupBox8.Location = new System.Drawing.Point(8, 776); this.groupBox8.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.groupBox8.Name = "groupBox8"; this.groupBox8.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4); this.groupBox8.Size = new System.Drawing.Size(482, 68); this.groupBox8.TabIndex = 15; this.groupBox8.TabStop = false; this.groupBox8.Text = "Recordings Directory"; // // btnBrowse // this.btnBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnBrowse.Enabled = false; this.btnBrowse.Location = new System.Drawing.Point(277, 29); this.btnBrowse.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnBrowse.Name = "btnBrowse"; this.btnBrowse.Size = new System.Drawing.Size(38, 31); this.btnBrowse.TabIndex = 17; this.btnBrowse.Text = "..."; this.btnBrowse.UseVisualStyleBackColor = true; this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click); // // tbFolderPath // this.tbFolderPath.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.tbFolderPath.Location = new System.Drawing.Point(9, 29); this.tbFolderPath.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tbFolderPath.Name = "tbFolderPath"; this.tbFolderPath.Size = new System.Drawing.Size(265, 27); this.tbFolderPath.TabIndex = 15; // // btnSetPath // this.btnSetPath.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnSetPath.Enabled = false; this.btnSetPath.Location = new System.Drawing.Point(365, 28); this.btnSetPath.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnSetPath.Name = "btnSetPath"; this.btnSetPath.Size = new System.Drawing.Size(107, 31); this.btnSetPath.TabIndex = 16; this.btnSetPath.Text = "Set Path"; this.btnSetPath.UseVisualStyleBackColor = true; this.btnSetPath.Click += new System.EventHandler(this.btnSetPath_Click); // // btnAdvanced // this.btnAdvanced.Location = new System.Drawing.Point(657, 799); this.btnAdvanced.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnAdvanced.Name = "btnAdvanced"; this.btnAdvanced.Size = new System.Drawing.Size(101, 36); this.btnAdvanced.TabIndex = 13; this.btnAdvanced.Text = "Advanced >>"; this.btnAdvanced.UseVisualStyleBackColor = true; this.btnAdvanced.Click += new System.EventHandler(this.btnAdvanced_Click); // // groupBox7 // this.groupBox7.Controls.Add(this.btnSetTransitionDuration); this.groupBox7.Controls.Add(this.btnGetTransitionDuration); this.groupBox7.Controls.Add(this.tbTransitionDuration); this.groupBox7.Location = new System.Drawing.Point(563, 668); this.groupBox7.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox7.Name = "groupBox7"; this.groupBox7.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox7.Size = new System.Drawing.Size(194, 81); this.groupBox7.TabIndex = 12; this.groupBox7.TabStop = false; this.groupBox7.Text = "Transition Duration"; // // btnSetTransitionDuration // this.btnSetTransitionDuration.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnSetTransitionDuration.Location = new System.Drawing.Point(129, 33); this.btnSetTransitionDuration.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnSetTransitionDuration.Name = "btnSetTransitionDuration"; this.btnSetTransitionDuration.Size = new System.Drawing.Size(54, 36); this.btnSetTransitionDuration.TabIndex = 2; this.btnSetTransitionDuration.Text = "Set"; this.btnSetTransitionDuration.UseVisualStyleBackColor = true; this.btnSetTransitionDuration.Click += new System.EventHandler(this.btnSetTransitionDuration_Click); // // btnGetTransitionDuration // this.btnGetTransitionDuration.Location = new System.Drawing.Point(9, 33); this.btnGetTransitionDuration.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnGetTransitionDuration.Name = "btnGetTransitionDuration"; this.btnGetTransitionDuration.Size = new System.Drawing.Size(55, 36); this.btnGetTransitionDuration.TabIndex = 1; this.btnGetTransitionDuration.Text = "Get"; this.btnGetTransitionDuration.UseVisualStyleBackColor = true; this.btnGetTransitionDuration.Click += new System.EventHandler(this.btnGetTransitionDuration_Click); // // tbTransitionDuration // this.tbTransitionDuration.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tbTransitionDuration.Increment = new decimal(new int[] { 50, 0, 0, 0}); this.tbTransitionDuration.Location = new System.Drawing.Point(67, 36); this.tbTransitionDuration.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tbTransitionDuration.Maximum = new decimal(new int[] { 120000, 0, 0, 0}); this.tbTransitionDuration.Name = "tbTransitionDuration"; this.tbTransitionDuration.Size = new System.Drawing.Size(53, 27); this.tbTransitionDuration.TabIndex = 0; // // groupBox6 // this.groupBox6.Controls.Add(this.btnSetCurrentTransition); this.groupBox6.Controls.Add(this.btnGetCurrentTransition); this.groupBox6.Controls.Add(this.tbTransition); this.groupBox6.Controls.Add(this.btnListTransitions); this.groupBox6.Controls.Add(this.tvTransitions); this.groupBox6.Location = new System.Drawing.Point(234, 401); this.groupBox6.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox6.Name = "groupBox6"; this.groupBox6.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox6.Size = new System.Drawing.Size(256, 373); this.groupBox6.TabIndex = 10; this.groupBox6.TabStop = false; this.groupBox6.Text = "Transitions"; // // btnSetCurrentTransition // this.btnSetCurrentTransition.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnSetCurrentTransition.Location = new System.Drawing.Point(138, 307); this.btnSetCurrentTransition.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnSetCurrentTransition.Name = "btnSetCurrentTransition"; this.btnSetCurrentTransition.Size = new System.Drawing.Size(107, 59); this.btnSetCurrentTransition.TabIndex = 5; this.btnSetCurrentTransition.Text = "Set\r\nCurTransition"; this.btnSetCurrentTransition.UseVisualStyleBackColor = true; this.btnSetCurrentTransition.Click += new System.EventHandler(this.btnSetCurrentTransition_Click); // // btnGetCurrentTransition // this.btnGetCurrentTransition.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnGetCurrentTransition.Location = new System.Drawing.Point(8, 307); this.btnGetCurrentTransition.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnGetCurrentTransition.Name = "btnGetCurrentTransition"; this.btnGetCurrentTransition.Size = new System.Drawing.Size(114, 59); this.btnGetCurrentTransition.TabIndex = 4; this.btnGetCurrentTransition.Text = "Get\r\nCurTransition"; this.btnGetCurrentTransition.UseVisualStyleBackColor = true; this.btnGetCurrentTransition.Click += new System.EventHandler(this.btnGetCurrentTransition_Click); // // tbTransition // this.tbTransition.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tbTransition.Location = new System.Drawing.Point(8, 267); this.tbTransition.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tbTransition.Name = "tbTransition"; this.tbTransition.Size = new System.Drawing.Size(237, 27); this.tbTransition.TabIndex = 3; // // btnListTransitions // this.btnListTransitions.Location = new System.Drawing.Point(8, 29); this.btnListTransitions.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnListTransitions.Name = "btnListTransitions"; this.btnListTransitions.Size = new System.Drawing.Size(114, 36); this.btnListTransitions.TabIndex = 2; this.btnListTransitions.Text = "ListTransitions"; this.btnListTransitions.UseVisualStyleBackColor = true; this.btnListTransitions.Click += new System.EventHandler(this.btnListTransitions_Click); // // tvTransitions // this.tvTransitions.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tvTransitions.Location = new System.Drawing.Point(8, 76); this.tvTransitions.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tvTransitions.Name = "tvTransitions"; this.tvTransitions.Size = new System.Drawing.Size(238, 180); this.tvTransitions.TabIndex = 1; this.tvTransitions.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.tvTransitions_NodeMouseClick); // // gbStatus // this.gbStatus.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.gbStatus.Controls.Add(this.tabStats); this.gbStatus.Location = new System.Drawing.Point(453, 19); this.gbStatus.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.gbStatus.Name = "gbStatus"; this.gbStatus.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); this.gbStatus.Size = new System.Drawing.Size(305, 269); this.gbStatus.TabIndex = 11; this.gbStatus.TabStop = false; // // tabStats // this.tabStats.Controls.Add(this.obsPage); this.tabStats.Controls.Add(this.streamPage); this.tabStats.Controls.Add(this.recPage); this.tabStats.Location = new System.Drawing.Point(4, 0); this.tabStats.Name = "tabStats"; this.tabStats.SelectedIndex = 0; this.tabStats.Size = new System.Drawing.Size(294, 262); this.tabStats.TabIndex = 1; // // obsPage // this.obsPage.Controls.Add(this.tableLayoutPanel3); this.obsPage.Location = new System.Drawing.Point(4, 29); this.obsPage.Name = "obsPage"; this.obsPage.Padding = new System.Windows.Forms.Padding(3); this.obsPage.Size = new System.Drawing.Size(286, 229); this.obsPage.TabIndex = 0; this.obsPage.Text = "OBS"; this.obsPage.UseVisualStyleBackColor = true; // // tableLayoutPanel3 // this.tableLayoutPanel3.ColumnCount = 2; this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 134F)); this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel3.Controls.Add(this.lblOutgoingMessages, 1, 10); this.tableLayoutPanel3.Controls.Add(this.lblIncomingMessages, 1, 9); this.tableLayoutPanel3.Controls.Add(this.lblDisk, 1, 8); this.tableLayoutPanel3.Controls.Add(this.lblMemory, 1, 7); this.tableLayoutPanel3.Controls.Add(this.lblCPU, 1, 6); this.tableLayoutPanel3.Controls.Add(this.lblFPS, 1, 5); this.tableLayoutPanel3.Controls.Add(this.lblAvgRender, 1, 4); this.tableLayoutPanel3.Controls.Add(this.lblSkipped, 1, 3); this.tableLayoutPanel3.Controls.Add(this.label26, 0, 1); this.tableLayoutPanel3.Controls.Add(this.label25, 0, 10); this.tableLayoutPanel3.Controls.Add(this.label24, 0, 0); this.tableLayoutPanel3.Controls.Add(this.label23, 0, 8); this.tableLayoutPanel3.Controls.Add(this.label22, 0, 9); this.tableLayoutPanel3.Controls.Add(this.lblOutputTotal, 1, 2); this.tableLayoutPanel3.Controls.Add(this.label20, 0, 7); this.tableLayoutPanel3.Controls.Add(this.label19, 0, 5); this.tableLayoutPanel3.Controls.Add(this.label18, 0, 6); this.tableLayoutPanel3.Controls.Add(this.label17, 0, 4); this.tableLayoutPanel3.Controls.Add(this.label16, 0, 2); this.tableLayoutPanel3.Controls.Add(this.label15, 0, 3); this.tableLayoutPanel3.Controls.Add(this.lblMissed, 0, 1); this.tableLayoutPanel3.Controls.Add(this.lblRendered, 1, 0); this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; this.tableLayoutPanel3.RowCount = 13; this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.Size = new System.Drawing.Size(286, 215); this.tableLayoutPanel3.TabIndex = 0; this.tableLayoutPanel3.Paint += new System.Windows.Forms.PaintEventHandler(this.tableLayoutPanel3_Paint); // // lblOutgoingMessages // this.lblOutgoingMessages.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblOutgoingMessages.AutoSize = true; this.lblOutgoingMessages.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblOutgoingMessages.Location = new System.Drawing.Point(139, 199); this.lblOutgoingMessages.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblOutgoingMessages.Name = "lblOutgoingMessages"; this.lblOutgoingMessages.Size = new System.Drawing.Size(142, 19); this.lblOutgoingMessages.TabIndex = 23; this.lblOutgoingMessages.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblIncomingMessages // this.lblIncomingMessages.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblIncomingMessages.AutoSize = true; this.lblIncomingMessages.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblIncomingMessages.Location = new System.Drawing.Point(139, 180); this.lblIncomingMessages.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblIncomingMessages.Name = "lblIncomingMessages"; this.lblIncomingMessages.Size = new System.Drawing.Size(142, 19); this.lblIncomingMessages.TabIndex = 22; this.lblIncomingMessages.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblDisk // this.lblDisk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblDisk.AutoSize = true; this.lblDisk.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblDisk.Location = new System.Drawing.Point(139, 160); this.lblDisk.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblDisk.Name = "lblDisk"; this.lblDisk.Size = new System.Drawing.Size(142, 19); this.lblDisk.TabIndex = 21; this.lblDisk.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblMemory // this.lblMemory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblMemory.AutoSize = true; this.lblMemory.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblMemory.Location = new System.Drawing.Point(139, 140); this.lblMemory.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblMemory.Name = "lblMemory"; this.lblMemory.Size = new System.Drawing.Size(142, 19); this.lblMemory.TabIndex = 20; this.lblMemory.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblCPU // this.lblCPU.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblCPU.AutoSize = true; this.lblCPU.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblCPU.Location = new System.Drawing.Point(139, 120); this.lblCPU.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblCPU.Name = "lblCPU"; this.lblCPU.Size = new System.Drawing.Size(142, 19); this.lblCPU.TabIndex = 19; this.lblCPU.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblFPS // this.lblFPS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblFPS.AutoSize = true; this.lblFPS.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblFPS.Location = new System.Drawing.Point(139, 100); this.lblFPS.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblFPS.Name = "lblFPS"; this.lblFPS.Size = new System.Drawing.Size(142, 19); this.lblFPS.TabIndex = 18; this.lblFPS.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblAvgRender // this.lblAvgRender.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblAvgRender.AutoSize = true; this.lblAvgRender.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblAvgRender.Location = new System.Drawing.Point(139, 80); this.lblAvgRender.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblAvgRender.Name = "lblAvgRender"; this.lblAvgRender.Size = new System.Drawing.Size(142, 19); this.lblAvgRender.TabIndex = 17; this.lblAvgRender.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblSkipped // this.lblSkipped.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblSkipped.AutoSize = true; this.lblSkipped.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblSkipped.Location = new System.Drawing.Point(139, 60); this.lblSkipped.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblSkipped.Name = "lblSkipped"; this.lblSkipped.Size = new System.Drawing.Size(142, 19); this.lblSkipped.TabIndex = 16; this.lblSkipped.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label26 // this.label26.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label26.AutoSize = true; this.label26.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label26.Location = new System.Drawing.Point(5, 20); this.label26.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label26.Name = "label26"; this.label26.Size = new System.Drawing.Size(124, 19); this.label26.TabIndex = 15; this.label26.Text = "Missed:"; this.label26.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label25 // this.label25.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label25.AutoSize = true; this.label25.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label25.Location = new System.Drawing.Point(5, 199); this.label25.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label25.Name = "label25"; this.label25.Size = new System.Drawing.Size(124, 19); this.label25.TabIndex = 14; this.label25.Text = "OUT Messages:"; this.label25.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label24 // this.label24.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label24.AutoSize = true; this.label24.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label24.Location = new System.Drawing.Point(5, 0); this.label24.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label24.Name = "label24"; this.label24.Size = new System.Drawing.Size(124, 19); this.label24.TabIndex = 13; this.label24.Text = "Frames Rendered:"; this.label24.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label23 // this.label23.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label23.AutoSize = true; this.label23.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label23.Location = new System.Drawing.Point(5, 160); this.label23.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label23.Name = "label23"; this.label23.Size = new System.Drawing.Size(124, 19); this.label23.TabIndex = 12; this.label23.Text = "Free Disk:"; this.label23.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label22 // this.label22.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label22.AutoSize = true; this.label22.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label22.Location = new System.Drawing.Point(5, 180); this.label22.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label22.Name = "label22"; this.label22.Size = new System.Drawing.Size(124, 19); this.label22.TabIndex = 11; this.label22.Text = "IN Messages:"; this.label22.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblOutputTotal // this.lblOutputTotal.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblOutputTotal.AutoSize = true; this.lblOutputTotal.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblOutputTotal.Location = new System.Drawing.Point(139, 40); this.lblOutputTotal.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblOutputTotal.Name = "lblOutputTotal"; this.lblOutputTotal.Size = new System.Drawing.Size(142, 19); this.lblOutputTotal.TabIndex = 10; this.lblOutputTotal.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label20 // this.label20.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label20.AutoSize = true; this.label20.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label20.Location = new System.Drawing.Point(5, 140); this.label20.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label20.Name = "label20"; this.label20.Size = new System.Drawing.Size(124, 19); this.label20.TabIndex = 9; this.label20.Text = "Memory:"; this.label20.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label19 // this.label19.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label19.AutoSize = true; this.label19.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label19.Location = new System.Drawing.Point(5, 100); this.label19.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label19.Name = "label19"; this.label19.Size = new System.Drawing.Size(124, 19); this.label19.TabIndex = 8; this.label19.Text = "FPS:"; this.label19.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label18 // this.label18.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label18.AutoSize = true; this.label18.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label18.Location = new System.Drawing.Point(5, 120); this.label18.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label18.Name = "label18"; this.label18.Size = new System.Drawing.Size(124, 19); this.label18.TabIndex = 7; this.label18.Text = "CPU:"; this.label18.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label17 // this.label17.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label17.AutoSize = true; this.label17.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label17.Location = new System.Drawing.Point(5, 80); this.label17.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label17.Name = "label17"; this.label17.Size = new System.Drawing.Size(124, 19); this.label17.TabIndex = 6; this.label17.Text = "Avg Render Time:"; this.label17.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; this.label17.Click += new System.EventHandler(this.label17_Click); // // label16 // this.label16.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label16.AutoSize = true; this.label16.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label16.Location = new System.Drawing.Point(5, 40); this.label16.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label16.Name = "label16"; this.label16.Size = new System.Drawing.Size(124, 19); this.label16.TabIndex = 5; this.label16.Text = "Output Total:"; this.label16.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label15 // this.label15.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label15.AutoSize = true; this.label15.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label15.Location = new System.Drawing.Point(5, 60); this.label15.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label15.Name = "label15"; this.label15.Size = new System.Drawing.Size(124, 19); this.label15.TabIndex = 4; this.label15.Text = "Skipped:"; this.label15.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblMissed // this.lblMissed.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblMissed.AutoSize = true; this.lblMissed.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblMissed.Location = new System.Drawing.Point(139, 20); this.lblMissed.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblMissed.Name = "lblMissed"; this.lblMissed.Size = new System.Drawing.Size(142, 19); this.lblMissed.TabIndex = 3; this.lblMissed.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblRendered // this.lblRendered.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblRendered.AutoSize = true; this.lblRendered.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblRendered.Location = new System.Drawing.Point(139, 0); this.lblRendered.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblRendered.Name = "lblRendered"; this.lblRendered.Size = new System.Drawing.Size(142, 19); this.lblRendered.TabIndex = 2; this.lblRendered.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // streamPage // this.streamPage.Controls.Add(this.tableLayoutPanel2); this.streamPage.Location = new System.Drawing.Point(4, 29); this.streamPage.Name = "streamPage"; this.streamPage.Padding = new System.Windows.Forms.Padding(3); this.streamPage.Size = new System.Drawing.Size(286, 229); this.streamPage.TabIndex = 1; this.streamPage.Text = "Stream"; this.streamPage.UseVisualStyleBackColor = true; // // tableLayoutPanel2 // this.tableLayoutPanel2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tableLayoutPanel2.ColumnCount = 2; this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 134F)); this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel2.Controls.Add(this.lblStreamSkippedFrames, 1, 6); this.tableLayoutPanel2.Controls.Add(this.label32, 0, 1); this.tableLayoutPanel2.Controls.Add(this.label31, 0, 0); this.tableLayoutPanel2.Controls.Add(this.lblStreamOutputBytes, 1, 7); this.tableLayoutPanel2.Controls.Add(this.lblStreamTotalFrames, 1, 5); this.tableLayoutPanel2.Controls.Add(this.lblStreamCongestion, 1, 4); this.tableLayoutPanel2.Controls.Add(this.lblStreamDuration, 1, 3); this.tableLayoutPanel2.Controls.Add(this.lblStreamTimeCode, 1, 2); this.tableLayoutPanel2.Controls.Add(this.lblStreamReconnect, 1, 1); this.tableLayoutPanel2.Controls.Add(this.lblStreamActive, 1, 0); this.tableLayoutPanel2.Controls.Add(this.label6, 0, 2); this.tableLayoutPanel2.Controls.Add(this.label7, 0, 3); this.tableLayoutPanel2.Controls.Add(this.label8, 0, 4); this.tableLayoutPanel2.Controls.Add(this.label9, 0, 5); this.tableLayoutPanel2.Controls.Add(this.label10, 0, 6); this.tableLayoutPanel2.Controls.Add(this.label11, 0, 7); this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0); this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; this.tableLayoutPanel2.RowCount = 9; this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel2.Size = new System.Drawing.Size(278, 208); this.tableLayoutPanel2.TabIndex = 1; // // lblStreamSkippedFrames // this.lblStreamSkippedFrames.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblStreamSkippedFrames.AutoSize = true; this.lblStreamSkippedFrames.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblStreamSkippedFrames.Location = new System.Drawing.Point(139, 120); this.lblStreamSkippedFrames.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblStreamSkippedFrames.Name = "lblStreamSkippedFrames"; this.lblStreamSkippedFrames.Size = new System.Drawing.Size(134, 19); this.lblStreamSkippedFrames.TabIndex = 17; this.lblStreamSkippedFrames.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label32 // this.label32.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label32.AutoSize = true; this.label32.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label32.Location = new System.Drawing.Point(5, 20); this.label32.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label32.Name = "label32"; this.label32.Size = new System.Drawing.Size(124, 19); this.label32.TabIndex = 16; this.label32.Text = "Reconnecting:"; this.label32.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label31 // this.label31.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label31.AutoSize = true; this.label31.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label31.Location = new System.Drawing.Point(5, 0); this.label31.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label31.Name = "label31"; this.label31.Size = new System.Drawing.Size(124, 19); this.label31.TabIndex = 15; this.label31.Text = "Streaming:"; this.label31.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblStreamOutputBytes // this.lblStreamOutputBytes.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblStreamOutputBytes.AutoSize = true; this.lblStreamOutputBytes.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblStreamOutputBytes.Location = new System.Drawing.Point(139, 140); this.lblStreamOutputBytes.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblStreamOutputBytes.Name = "lblStreamOutputBytes"; this.lblStreamOutputBytes.Size = new System.Drawing.Size(134, 19); this.lblStreamOutputBytes.TabIndex = 14; this.lblStreamOutputBytes.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblStreamTotalFrames // this.lblStreamTotalFrames.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblStreamTotalFrames.AutoSize = true; this.lblStreamTotalFrames.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblStreamTotalFrames.Location = new System.Drawing.Point(139, 100); this.lblStreamTotalFrames.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblStreamTotalFrames.Name = "lblStreamTotalFrames"; this.lblStreamTotalFrames.Size = new System.Drawing.Size(134, 19); this.lblStreamTotalFrames.TabIndex = 13; this.lblStreamTotalFrames.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblStreamCongestion // this.lblStreamCongestion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblStreamCongestion.AutoSize = true; this.lblStreamCongestion.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblStreamCongestion.Location = new System.Drawing.Point(139, 80); this.lblStreamCongestion.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblStreamCongestion.Name = "lblStreamCongestion"; this.lblStreamCongestion.Size = new System.Drawing.Size(134, 19); this.lblStreamCongestion.TabIndex = 12; this.lblStreamCongestion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblStreamDuration // this.lblStreamDuration.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblStreamDuration.AutoSize = true; this.lblStreamDuration.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblStreamDuration.Location = new System.Drawing.Point(139, 60); this.lblStreamDuration.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblStreamDuration.Name = "lblStreamDuration"; this.lblStreamDuration.Size = new System.Drawing.Size(134, 19); this.lblStreamDuration.TabIndex = 11; this.lblStreamDuration.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblStreamTimeCode // this.lblStreamTimeCode.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblStreamTimeCode.AutoSize = true; this.lblStreamTimeCode.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblStreamTimeCode.Location = new System.Drawing.Point(139, 40); this.lblStreamTimeCode.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblStreamTimeCode.Name = "lblStreamTimeCode"; this.lblStreamTimeCode.Size = new System.Drawing.Size(134, 19); this.lblStreamTimeCode.TabIndex = 10; this.lblStreamTimeCode.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblStreamReconnect // this.lblStreamReconnect.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblStreamReconnect.AutoSize = true; this.lblStreamReconnect.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblStreamReconnect.Location = new System.Drawing.Point(139, 20); this.lblStreamReconnect.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblStreamReconnect.Name = "lblStreamReconnect"; this.lblStreamReconnect.Size = new System.Drawing.Size(134, 19); this.lblStreamReconnect.TabIndex = 9; this.lblStreamReconnect.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblStreamActive // this.lblStreamActive.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblStreamActive.AutoSize = true; this.lblStreamActive.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblStreamActive.Location = new System.Drawing.Point(139, 0); this.lblStreamActive.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblStreamActive.Name = "lblStreamActive"; this.lblStreamActive.Size = new System.Drawing.Size(134, 19); this.lblStreamActive.TabIndex = 8; this.lblStreamActive.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label6 // this.label6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label6.AutoSize = true; this.label6.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label6.Location = new System.Drawing.Point(5, 40); this.label6.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label6.Name = "label6"; this.label6.Size = new System.Drawing.Size(124, 19); this.label6.TabIndex = 1; this.label6.Text = "Time Code:"; this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label7 // this.label7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label7.AutoSize = true; this.label7.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label7.Location = new System.Drawing.Point(5, 60); this.label7.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label7.Name = "label7"; this.label7.Size = new System.Drawing.Size(124, 19); this.label7.TabIndex = 2; this.label7.Text = "Duration:"; this.label7.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label8 // this.label8.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label8.AutoSize = true; this.label8.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label8.Location = new System.Drawing.Point(5, 80); this.label8.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label8.Name = "label8"; this.label8.Size = new System.Drawing.Size(124, 19); this.label8.TabIndex = 3; this.label8.Text = "Congestion:"; this.label8.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label9 // this.label9.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label9.AutoSize = true; this.label9.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label9.Location = new System.Drawing.Point(5, 100); this.label9.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label9.Name = "label9"; this.label9.Size = new System.Drawing.Size(124, 19); this.label9.TabIndex = 4; this.label9.Text = "Total Frames:"; this.label9.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label10 // this.label10.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label10.AutoSize = true; this.label10.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label10.Location = new System.Drawing.Point(5, 120); this.label10.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label10.Name = "label10"; this.label10.Size = new System.Drawing.Size(124, 19); this.label10.TabIndex = 5; this.label10.Text = "Skipped:"; this.label10.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label11 // this.label11.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label11.AutoSize = true; this.label11.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label11.Location = new System.Drawing.Point(5, 140); this.label11.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label11.Name = "label11"; this.label11.Size = new System.Drawing.Size(124, 19); this.label11.TabIndex = 6; this.label11.Text = "OUT Bytes:"; this.label11.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // recPage // this.recPage.Controls.Add(this.tableLayoutPanel5); this.recPage.Location = new System.Drawing.Point(4, 29); this.recPage.Name = "recPage"; this.recPage.Size = new System.Drawing.Size(286, 229); this.recPage.TabIndex = 2; this.recPage.Text = "Recording"; this.recPage.UseVisualStyleBackColor = true; // // tableLayoutPanel5 // this.tableLayoutPanel5.ColumnCount = 2; this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 134F)); this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel5.Controls.Add(this.lblRecordingBytes, 1, 4); this.tableLayoutPanel5.Controls.Add(this.lblRecordingDuration, 1, 3); this.tableLayoutPanel5.Controls.Add(this.lblRecordingTimeCode, 1, 2); this.tableLayoutPanel5.Controls.Add(this.lblRecordingPaused, 1, 1); this.tableLayoutPanel5.Controls.Add(this.lblRecording, 1, 0); this.tableLayoutPanel5.Controls.Add(this.label30, 0, 4); this.tableLayoutPanel5.Controls.Add(this.label29, 0, 3); this.tableLayoutPanel5.Controls.Add(this.label28, 0, 2); this.tableLayoutPanel5.Controls.Add(this.label27, 0, 1); this.tableLayoutPanel5.Controls.Add(this.label21, 0, 0); this.tableLayoutPanel5.Location = new System.Drawing.Point(4, 0); this.tableLayoutPanel5.Name = "tableLayoutPanel5"; this.tableLayoutPanel5.RowCount = 6; this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel5.Size = new System.Drawing.Size(278, 227); this.tableLayoutPanel5.TabIndex = 0; // // lblRecordingBytes // this.lblRecordingBytes.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblRecordingBytes.AutoSize = true; this.lblRecordingBytes.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblRecordingBytes.Location = new System.Drawing.Point(139, 80); this.lblRecordingBytes.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblRecordingBytes.Name = "lblRecordingBytes"; this.lblRecordingBytes.Size = new System.Drawing.Size(134, 19); this.lblRecordingBytes.TabIndex = 23; this.lblRecordingBytes.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblRecordingDuration // this.lblRecordingDuration.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblRecordingDuration.AutoSize = true; this.lblRecordingDuration.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblRecordingDuration.Location = new System.Drawing.Point(139, 60); this.lblRecordingDuration.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblRecordingDuration.Name = "lblRecordingDuration"; this.lblRecordingDuration.Size = new System.Drawing.Size(134, 19); this.lblRecordingDuration.TabIndex = 22; this.lblRecordingDuration.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblRecordingTimeCode // this.lblRecordingTimeCode.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblRecordingTimeCode.AutoSize = true; this.lblRecordingTimeCode.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblRecordingTimeCode.Location = new System.Drawing.Point(139, 40); this.lblRecordingTimeCode.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblRecordingTimeCode.Name = "lblRecordingTimeCode"; this.lblRecordingTimeCode.Size = new System.Drawing.Size(134, 19); this.lblRecordingTimeCode.TabIndex = 21; this.lblRecordingTimeCode.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblRecordingPaused // this.lblRecordingPaused.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblRecordingPaused.AutoSize = true; this.lblRecordingPaused.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblRecordingPaused.Location = new System.Drawing.Point(139, 20); this.lblRecordingPaused.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblRecordingPaused.Name = "lblRecordingPaused"; this.lblRecordingPaused.Size = new System.Drawing.Size(134, 19); this.lblRecordingPaused.TabIndex = 20; this.lblRecordingPaused.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblRecording // this.lblRecording.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblRecording.AutoSize = true; this.lblRecording.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.lblRecording.Location = new System.Drawing.Point(139, 0); this.lblRecording.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.lblRecording.Name = "lblRecording"; this.lblRecording.Size = new System.Drawing.Size(134, 19); this.lblRecording.TabIndex = 19; this.lblRecording.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label30 // this.label30.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label30.AutoSize = true; this.label30.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label30.Location = new System.Drawing.Point(5, 80); this.label30.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label30.Name = "label30"; this.label30.Size = new System.Drawing.Size(124, 19); this.label30.TabIndex = 18; this.label30.Text = "Bytes:"; this.label30.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label29 // this.label29.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label29.AutoSize = true; this.label29.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label29.Location = new System.Drawing.Point(5, 60); this.label29.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label29.Name = "label29"; this.label29.Size = new System.Drawing.Size(124, 19); this.label29.TabIndex = 17; this.label29.Text = "Duration:"; this.label29.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label28 // this.label28.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label28.AutoSize = true; this.label28.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label28.Location = new System.Drawing.Point(5, 40); this.label28.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label28.Name = "label28"; this.label28.Size = new System.Drawing.Size(124, 19); this.label28.TabIndex = 16; this.label28.Text = "Time Code:"; this.label28.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label27 // this.label27.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label27.AutoSize = true; this.label27.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label27.Location = new System.Drawing.Point(5, 20); this.label27.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label27.Name = "label27"; this.label27.Size = new System.Drawing.Size(124, 19); this.label27.TabIndex = 15; this.label27.Text = "Paused:"; this.label27.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label21 // this.label21.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label21.AutoSize = true; this.label21.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label21.Location = new System.Drawing.Point(5, 0); this.label21.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label21.Name = "label21"; this.label21.Size = new System.Drawing.Size(124, 19); this.label21.TabIndex = 14; this.label21.Text = "Recording:"; this.label21.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // groupBox5 // this.groupBox5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.groupBox5.Controls.Add(this.btnPauseRecording); this.groupBox5.Controls.Add(this.btnToggleRecording); this.groupBox5.Controls.Add(this.btnToggleStreaming); this.groupBox5.Location = new System.Drawing.Point(563, 441); this.groupBox5.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox5.Name = "groupBox5"; this.groupBox5.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox5.Size = new System.Drawing.Size(193, 121); this.groupBox5.TabIndex = 10; this.groupBox5.TabStop = false; this.groupBox5.Text = "Streaming / Recording"; // // btnPauseRecording // this.btnPauseRecording.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnPauseRecording.Location = new System.Drawing.Point(157, 75); this.btnPauseRecording.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnPauseRecording.Name = "btnPauseRecording"; this.btnPauseRecording.Size = new System.Drawing.Size(27, 36); this.btnPauseRecording.TabIndex = 2; this.btnPauseRecording.Text = "||"; this.btnPauseRecording.UseVisualStyleBackColor = true; this.btnPauseRecording.Click += new System.EventHandler(this.btnPauseRecording_Click); // // btnToggleRecording // this.btnToggleRecording.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnToggleRecording.Location = new System.Drawing.Point(6, 75); this.btnToggleRecording.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnToggleRecording.Name = "btnToggleRecording"; this.btnToggleRecording.Size = new System.Drawing.Size(151, 36); this.btnToggleRecording.TabIndex = 1; this.btnToggleRecording.Text = "State unknown"; this.btnToggleRecording.UseVisualStyleBackColor = true; this.btnToggleRecording.Click += new System.EventHandler(this.btnToggleRecording_Click); // // btnToggleStreaming // this.btnToggleStreaming.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnToggleStreaming.Location = new System.Drawing.Point(6, 31); this.btnToggleStreaming.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnToggleStreaming.Name = "btnToggleStreaming"; this.btnToggleStreaming.Size = new System.Drawing.Size(178, 36); this.btnToggleStreaming.TabIndex = 0; this.btnToggleStreaming.Text = "State unknown"; this.btnToggleStreaming.UseVisualStyleBackColor = true; this.btnToggleStreaming.Click += new System.EventHandler(this.btnToggleStreaming_Click); // // groupBox4 // this.groupBox4.Controls.Add(this.btnSetCurrentProfile); this.groupBox4.Controls.Add(this.btnGetCurrentProfile); this.groupBox4.Controls.Add(this.tbProfile); this.groupBox4.Controls.Add(this.btnListProfiles); this.groupBox4.Controls.Add(this.tvProfiles); this.groupBox4.Location = new System.Drawing.Point(8, 401); this.groupBox4.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox4.Name = "groupBox4"; this.groupBox4.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox4.Size = new System.Drawing.Size(218, 373); this.groupBox4.TabIndex = 9; this.groupBox4.TabStop = false; this.groupBox4.Text = "Profiles"; // // btnSetCurrentProfile // this.btnSetCurrentProfile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnSetCurrentProfile.Location = new System.Drawing.Point(118, 307); this.btnSetCurrentProfile.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnSetCurrentProfile.Name = "btnSetCurrentProfile"; this.btnSetCurrentProfile.Size = new System.Drawing.Size(91, 59); this.btnSetCurrentProfile.TabIndex = 5; this.btnSetCurrentProfile.Text = "Set\r\nCurProfile"; this.btnSetCurrentProfile.UseVisualStyleBackColor = true; this.btnSetCurrentProfile.Click += new System.EventHandler(this.btnSetCurrentProfile_Click); // // btnGetCurrentProfile // this.btnGetCurrentProfile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnGetCurrentProfile.Location = new System.Drawing.Point(8, 307); this.btnGetCurrentProfile.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnGetCurrentProfile.Name = "btnGetCurrentProfile"; this.btnGetCurrentProfile.Size = new System.Drawing.Size(91, 59); this.btnGetCurrentProfile.TabIndex = 4; this.btnGetCurrentProfile.Text = "Get\r\nCurProfile"; this.btnGetCurrentProfile.UseVisualStyleBackColor = true; this.btnGetCurrentProfile.Click += new System.EventHandler(this.btnGetCurrentProfile_Click); // // tbProfile // this.tbProfile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tbProfile.Location = new System.Drawing.Point(8, 267); this.tbProfile.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tbProfile.Name = "tbProfile"; this.tbProfile.Size = new System.Drawing.Size(201, 27); this.tbProfile.TabIndex = 3; // // btnListProfiles // this.btnListProfiles.Location = new System.Drawing.Point(8, 29); this.btnListProfiles.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnListProfiles.Name = "btnListProfiles"; this.btnListProfiles.Size = new System.Drawing.Size(106, 36); this.btnListProfiles.TabIndex = 2; this.btnListProfiles.Text = "ListProfiles"; this.btnListProfiles.UseVisualStyleBackColor = true; this.btnListProfiles.Click += new System.EventHandler(this.btnListProfiles_Click); // // tvProfiles // this.tvProfiles.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tvProfiles.Location = new System.Drawing.Point(8, 76); this.tvProfiles.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tvProfiles.Name = "tvProfiles"; this.tvProfiles.Size = new System.Drawing.Size(202, 180); this.tvProfiles.TabIndex = 1; this.tvProfiles.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.tvProfiles_NodeMouseClick); // // groupBox2 // this.groupBox2.Controls.Add(this.btnSetCurrentSceneCol); this.groupBox2.Controls.Add(this.btnGetCurrentSceneCol); this.groupBox2.Controls.Add(this.tbSceneCol); this.groupBox2.Controls.Add(this.btnListSceneCol); this.groupBox2.Controls.Add(this.tvSceneCols); this.groupBox2.Location = new System.Drawing.Point(216, 19); this.groupBox2.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox2.Name = "groupBox2"; this.groupBox2.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox2.Size = new System.Drawing.Size(213, 373); this.groupBox2.TabIndex = 8; this.groupBox2.TabStop = false; this.groupBox2.Text = "Scene Collections"; // // btnSetCurrentSceneCol // this.btnSetCurrentSceneCol.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnSetCurrentSceneCol.Location = new System.Drawing.Point(111, 307); this.btnSetCurrentSceneCol.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnSetCurrentSceneCol.Name = "btnSetCurrentSceneCol"; this.btnSetCurrentSceneCol.Size = new System.Drawing.Size(91, 59); this.btnSetCurrentSceneCol.TabIndex = 5; this.btnSetCurrentSceneCol.Text = "Set\r\nCurSC"; this.btnSetCurrentSceneCol.UseVisualStyleBackColor = true; this.btnSetCurrentSceneCol.Click += new System.EventHandler(this.btnSetCurrentSceneCol_Click); // // btnGetCurrentSceneCol // this.btnGetCurrentSceneCol.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnGetCurrentSceneCol.Location = new System.Drawing.Point(8, 307); this.btnGetCurrentSceneCol.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnGetCurrentSceneCol.Name = "btnGetCurrentSceneCol"; this.btnGetCurrentSceneCol.Size = new System.Drawing.Size(91, 59); this.btnGetCurrentSceneCol.TabIndex = 4; this.btnGetCurrentSceneCol.Text = "Get\r\nCurSC"; this.btnGetCurrentSceneCol.UseVisualStyleBackColor = true; this.btnGetCurrentSceneCol.Click += new System.EventHandler(this.btnGetCurrentSceneCol_Click); // // tbSceneCol // this.tbSceneCol.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tbSceneCol.Location = new System.Drawing.Point(8, 267); this.tbSceneCol.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tbSceneCol.Name = "tbSceneCol"; this.tbSceneCol.Size = new System.Drawing.Size(194, 27); this.tbSceneCol.TabIndex = 3; // // btnListSceneCol // this.btnListSceneCol.Location = new System.Drawing.Point(8, 29); this.btnListSceneCol.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.btnListSceneCol.Name = "btnListSceneCol"; this.btnListSceneCol.Size = new System.Drawing.Size(167, 36); this.btnListSceneCol.TabIndex = 2; this.btnListSceneCol.Text = "ListSceneCollections"; this.btnListSceneCol.UseVisualStyleBackColor = true; this.btnListSceneCol.Click += new System.EventHandler(this.btnListSceneCol_Click); // // tvSceneCols // this.tvSceneCols.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tvSceneCols.Location = new System.Drawing.Point(8, 76); this.tvSceneCols.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tvSceneCols.Name = "tvSceneCols"; this.tvSceneCols.Size = new System.Drawing.Size(195, 180); this.tvSceneCols.TabIndex = 1; this.tvSceneCols.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.tvSceneCols_NodeMouseClick); // // groupBox3 // this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.groupBox3.Controls.Add(this.tableLayoutPanel1); this.groupBox3.Location = new System.Drawing.Point(536, 297); this.groupBox3.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox3.Name = "groupBox3"; this.groupBox3.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); this.groupBox3.Size = new System.Drawing.Size(222, 136); this.groupBox3.TabIndex = 7; this.groupBox3.TabStop = false; this.groupBox3.Text = "Version Info"; // // tableLayoutPanel1 // this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tableLayoutPanel1.ColumnCount = 2; this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 119F)); this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel1.Controls.Add(this.tbOBSVersion, 1, 1); this.tableLayoutPanel1.Controls.Add(this.tbPluginVersion, 1, 0); this.tableLayoutPanel1.Controls.Add(this.label3, 0, 0); this.tableLayoutPanel1.Controls.Add(this.label5, 0, 1); this.tableLayoutPanel1.Location = new System.Drawing.Point(9, 29); this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 3; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 31F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 31F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 31F)); this.tableLayoutPanel1.Size = new System.Drawing.Size(203, 97); this.tableLayoutPanel1.TabIndex = 1; // // tbOBSVersion // this.tbOBSVersion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.tbOBSVersion.AutoSize = true; this.tbOBSVersion.Location = new System.Drawing.Point(124, 36); this.tbOBSVersion.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.tbOBSVersion.Name = "tbOBSVersion"; this.tbOBSVersion.Size = new System.Drawing.Size(74, 20); this.tbOBSVersion.TabIndex = 5; this.tbOBSVersion.Text = "???"; this.tbOBSVersion.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // tbPluginVersion // this.tbPluginVersion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.tbPluginVersion.AutoSize = true; this.tbPluginVersion.Location = new System.Drawing.Point(124, 5); this.tbPluginVersion.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.tbPluginVersion.Name = "tbPluginVersion"; this.tbPluginVersion.Size = new System.Drawing.Size(74, 20); this.tbPluginVersion.TabIndex = 3; this.tbPluginVersion.Text = "???"; this.tbPluginVersion.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // label3 // this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label3.AutoSize = true; this.label3.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label3.Location = new System.Drawing.Point(5, 0); this.label3.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(109, 31); this.label3.TabIndex = 0; this.label3.Text = "OBS WS Version :"; this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // label5 // this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label5.AutoSize = true; this.label5.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label5.Location = new System.Drawing.Point(5, 37); this.label5.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(109, 19); this.label5.TabIndex = 2; this.label5.Text = "OBS Version :"; this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // button3 // this.button3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.button3.Location = new System.Drawing.Point(299, 326); this.button3.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.button3.Name = "button3"; this.button3.Size = new System.Drawing.Size(88, 23); this.button3.TabIndex = 15; this.button3.Text = "Set Path"; this.button3.UseVisualStyleBackColor = true; // // openFileDialog1 // this.openFileDialog1.FileName = "openFileDialog1"; // // label13 // this.label13.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label13.AutoSize = true; this.label13.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label13.Location = new System.Drawing.Point(139, 40); this.label13.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label13.Name = "label13"; this.label13.Size = new System.Drawing.Size(56, 19); this.label13.TabIndex = 23; this.label13.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label14 // this.label14.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.label14.AutoSize = true; this.label14.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label14.Location = new System.Drawing.Point(139, 0); this.label14.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); this.label14.Name = "label14"; this.label14.Size = new System.Drawing.Size(56, 19); this.label14.TabIndex = 22; this.label14.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // tableLayoutPanel4 // this.tableLayoutPanel4.ColumnCount = 2; this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 134F)); this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel4.Controls.Add(this.label13, 1, 10); this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 0); this.tableLayoutPanel4.Name = "tableLayoutPanel4"; this.tableLayoutPanel4.RowCount = 11; this.tableLayoutPanel4.Size = new System.Drawing.Size(200, 100); this.tableLayoutPanel4.TabIndex = 0; // // fileSystemWatcher1 // this.fileSystemWatcher1.EnableRaisingEvents = true; this.fileSystemWatcher1.SynchronizingObject = this; // // MainWindow // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(798, 924); this.Controls.Add(this.gbControls); this.Controls.Add(this.label2); this.Controls.Add(this.label1); this.Controls.Add(this.txtServerPassword); this.Controls.Add(this.txtServerIP); this.Controls.Add(this.btnConnect); this.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); this.Name = "MainWindow"; this.Text = "obs-websocket client"; this.Load += new System.EventHandler(this.MainWindow_Load); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); this.gbControls.ResumeLayout(false); this.groupBox9.ResumeLayout(false); this.groupBox9.PerformLayout(); this.groupBox8.ResumeLayout(false); this.groupBox8.PerformLayout(); this.groupBox7.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.tbTransitionDuration)).EndInit(); this.groupBox6.ResumeLayout(false); this.groupBox6.PerformLayout(); this.gbStatus.ResumeLayout(false); this.tabStats.ResumeLayout(false); this.obsPage.ResumeLayout(false); this.tableLayoutPanel3.ResumeLayout(false); this.tableLayoutPanel3.PerformLayout(); this.streamPage.ResumeLayout(false); this.tableLayoutPanel2.ResumeLayout(false); this.tableLayoutPanel2.PerformLayout(); this.recPage.ResumeLayout(false); this.tableLayoutPanel5.ResumeLayout(false); this.tableLayoutPanel5.PerformLayout(); this.groupBox5.ResumeLayout(false); this.groupBox4.ResumeLayout(false); this.groupBox4.PerformLayout(); this.groupBox2.ResumeLayout(false); this.groupBox2.PerformLayout(); this.groupBox3.ResumeLayout(false); this.tableLayoutPanel1.ResumeLayout(false); this.tableLayoutPanel1.PerformLayout(); this.tableLayoutPanel4.ResumeLayout(false); this.tableLayoutPanel4.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.fileSystemWatcher1)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Button btnConnect; private System.Windows.Forms.TextBox txtServerIP; private System.Windows.Forms.TextBox txtServerPassword; private System.Windows.Forms.TreeView tvScenes; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.Button btnListScenes; private System.Windows.Forms.Button btnGetCurrentScene; private System.Windows.Forms.Button btnSetCurrentScene; private System.Windows.Forms.TextBox tbCurrentScene; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.GroupBox gbControls; private System.Windows.Forms.GroupBox groupBox3; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; private System.Windows.Forms.Label tbOBSVersion; private System.Windows.Forms.Label tbPluginVersion; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label5; private System.Windows.Forms.GroupBox groupBox4; private System.Windows.Forms.Button btnSetCurrentProfile; private System.Windows.Forms.Button btnGetCurrentProfile; private System.Windows.Forms.TextBox tbProfile; private System.Windows.Forms.Button btnListProfiles; private System.Windows.Forms.TreeView tvProfiles; private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.Button btnSetCurrentSceneCol; private System.Windows.Forms.Button btnGetCurrentSceneCol; private System.Windows.Forms.TextBox tbSceneCol; private System.Windows.Forms.Button btnListSceneCol; private System.Windows.Forms.TreeView tvSceneCols; private System.Windows.Forms.GroupBox groupBox5; private System.Windows.Forms.Button btnToggleRecording; private System.Windows.Forms.Button btnToggleStreaming; private System.Windows.Forms.GroupBox gbStatus; private System.Windows.Forms.GroupBox groupBox6; private System.Windows.Forms.Button btnSetCurrentTransition; private System.Windows.Forms.Button btnGetCurrentTransition; private System.Windows.Forms.TextBox tbTransition; private System.Windows.Forms.Button btnListTransitions; private System.Windows.Forms.TreeView tvTransitions; private System.Windows.Forms.GroupBox groupBox7; private System.Windows.Forms.Button btnSetTransitionDuration; private System.Windows.Forms.Button btnGetTransitionDuration; private System.Windows.Forms.NumericUpDown tbTransitionDuration; private System.Windows.Forms.Button btnAdvanced; private System.Windows.Forms.Button button3; private System.Windows.Forms.OpenFileDialog openFileDialog1; private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1; private System.Windows.Forms.GroupBox groupBox8; private System.Windows.Forms.Button btnBrowse; private System.Windows.Forms.TextBox tbFolderPath; private System.Windows.Forms.Button btnSetPath; private System.Windows.Forms.GroupBox groupBox9; private System.Windows.Forms.Label lblVirtualCamStatus; private System.Windows.Forms.Label label4; private System.Windows.Forms.Button btnVirtualCamToggle; private System.Windows.Forms.Button btnVirtualCamStop; private System.Windows.Forms.Button btnVirtualCamStart; private System.Windows.Forms.TabControl tabStats; private System.Windows.Forms.TabPage obsPage; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; private System.Windows.Forms.TabPage streamPage; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; private System.Windows.Forms.Label lblStreamOutputBytes; private System.Windows.Forms.Label lblStreamTotalFrames; private System.Windows.Forms.Label lblStreamCongestion; private System.Windows.Forms.Label lblStreamDuration; private System.Windows.Forms.Label lblStreamTimeCode; private System.Windows.Forms.Label lblStreamReconnect; private System.Windows.Forms.Label lblStreamActive; private System.Windows.Forms.Label label6; private System.Windows.Forms.Label label7; private System.Windows.Forms.Label label8; private System.Windows.Forms.Label label9; private System.Windows.Forms.Label label10; private System.Windows.Forms.Label label11; private System.Windows.Forms.TabPage recPage; private System.Windows.Forms.Label lblRendered; private System.Windows.Forms.Label label20; private System.Windows.Forms.Label label19; private System.Windows.Forms.Label label18; private System.Windows.Forms.Label label17; private System.Windows.Forms.Label label16; private System.Windows.Forms.Label label15; private System.Windows.Forms.Label lblMissed; private System.Windows.Forms.Label label26; private System.Windows.Forms.Label label25; private System.Windows.Forms.Label label24; private System.Windows.Forms.Label label23; private System.Windows.Forms.Label label22; private System.Windows.Forms.Label lblOutputTotal; private System.Windows.Forms.Label lblOutgoingMessages; private System.Windows.Forms.Label lblIncomingMessages; private System.Windows.Forms.Label lblDisk; private System.Windows.Forms.Label lblMemory; private System.Windows.Forms.Label lblCPU; private System.Windows.Forms.Label lblFPS; private System.Windows.Forms.Label lblAvgRender; private System.Windows.Forms.Label lblSkipped; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5; private System.Windows.Forms.Label label13; private System.Windows.Forms.Label label14; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; private System.Windows.Forms.Label lblRecordingBytes; private System.Windows.Forms.Label lblRecordingDuration; private System.Windows.Forms.Label lblRecordingTimeCode; private System.Windows.Forms.Label lblRecordingPaused; private System.Windows.Forms.Label lblRecording; private System.Windows.Forms.Label label30; private System.Windows.Forms.Label label29; private System.Windows.Forms.Label label28; private System.Windows.Forms.Label label27; private System.Windows.Forms.Label label21; private System.Windows.Forms.Button btnPauseRecording; private System.Windows.Forms.Label label32; private System.Windows.Forms.Label label31; private System.Windows.Forms.Label lblStreamSkippedFrames; private System.IO.FileSystemWatcher fileSystemWatcher1; } } ================================================ FILE: TestClient/MainWindow.cs ================================================ /* TestClient for obs-websocket-dotnet Copyright (C) 2021 Stéphane Lepin, BarRaider This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see */ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using System.Linq; using OBSWebsocketDotNet; using OBSWebsocketDotNet.Types; using OBSWebsocketDotNet.Types.Events; namespace TestClient { public partial class MainWindow : Form { protected OBSWebsocket obs; private CancellationTokenSource keepAliveTokenSource; private readonly int keepAliveInterval = 500; public MainWindow() { InitializeComponent(); obs = new OBSWebsocket(); obs.Connected += onConnect; obs.Disconnected += onDisconnect; obs.CurrentProgramSceneChanged += onCurrentProgramSceneChanged; obs.CurrentSceneCollectionChanged += onSceneCollectionChanged; obs.CurrentProfileChanged += onCurrentProfileChanged; obs.CurrentSceneTransitionChanged += onCurrentSceneTransitionChanged; obs.CurrentSceneTransitionDurationChanged += onCurrentSceneTransitionDurationChanged; obs.StreamStateChanged += onStreamStateChanged; obs.RecordStateChanged += onRecordStateChanged; obs.VirtualcamStateChanged += onVirtualCamStateChanged; } private void onConnect(object sender, EventArgs e) { BeginInvoke((MethodInvoker)(() => { txtServerIP.Enabled = false; txtServerPassword.Enabled = false; btnConnect.Text = "Disconnect"; gbControls.Enabled = true; var versionInfo = obs.GetVersion(); tbPluginVersion.Text = versionInfo.PluginVersion; tbOBSVersion.Text = versionInfo.OBSStudioVersion; btnListScenes.PerformClick(); btnGetCurrentScene.PerformClick(); btnListSceneCol.PerformClick(); btnGetCurrentSceneCol.PerformClick(); btnListProfiles.PerformClick(); btnGetCurrentProfile.PerformClick(); btnListTransitions.PerformClick(); btnGetCurrentTransition.PerformClick(); btnGetTransitionDuration.PerformClick(); tbFolderPath.Text = obs.GetRecordDirectory().ToString(); var streamStatus = obs.GetStreamStatus(); if (streamStatus.IsActive) { onStreamStateChanged(obs, new StreamStateChangedEventArgs(new OutputStateChanged() { IsActive = true, StateStr = nameof(OutputState.OBS_WEBSOCKET_OUTPUT_STARTED) })); } else { onStreamStateChanged(obs, new StreamStateChangedEventArgs(new OutputStateChanged() { IsActive = false, StateStr = nameof(OutputState.OBS_WEBSOCKET_OUTPUT_STOPPED) })); } var recordStatus = obs.GetRecordStatus(); if (recordStatus.IsRecording) { onRecordStateChanged(obs, new RecordStateChangedEventArgs(new RecordStateChanged() { IsActive = true, StateStr = nameof(OutputState.OBS_WEBSOCKET_OUTPUT_STARTED) })); } else { onRecordStateChanged(obs, new RecordStateChangedEventArgs(new RecordStateChanged() { IsActive = false, StateStr = nameof(OutputState.OBS_WEBSOCKET_OUTPUT_STOPPED) })); } var camStatus = obs.GetVirtualCamStatus(); if (camStatus.IsActive) { onVirtualCamStateChanged(this, new VirtualcamStateChangedEventArgs(new OutputStateChanged() { IsActive = true, StateStr = nameof(OutputState.OBS_WEBSOCKET_OUTPUT_STARTED) })); } else { onVirtualCamStateChanged(this, new VirtualcamStateChangedEventArgs(new OutputStateChanged() { IsActive = false, StateStr = nameof(OutputState.OBS_WEBSOCKET_OUTPUT_STOPPED) })); } keepAliveTokenSource = new CancellationTokenSource(); CancellationToken keepAliveToken = keepAliveTokenSource.Token; Task statPollKeepAlive = Task.Factory.StartNew(() => { while (true) { Thread.Sleep(keepAliveInterval); if (keepAliveToken.IsCancellationRequested) { break; } BeginInvoke((MethodInvoker)(() => { switch (tabStats.SelectedIndex) { case 0: // OBS var stats = obs.GetStats(); UpdateOBSStats(stats); break; case 1: // Stream var streamStats = obs.GetStreamStatus(); UpdateStreamStats(streamStats); break; case 2: // Recording var recStats = obs.GetRecordStatus(); UpdateRecordingStats(recStats); break; } })); } }, keepAliveToken, TaskCreationOptions.LongRunning, TaskScheduler.Default); })); } private void onDisconnect(object sender, OBSWebsocketDotNet.Communication.ObsDisconnectionInfo e) { BeginInvoke((MethodInvoker)(() => { if (keepAliveTokenSource != null) { keepAliveTokenSource.Cancel(); } gbControls.Enabled = false; txtServerIP.Enabled = true; txtServerPassword.Enabled = true; btnConnect.Text = "Connect"; if (e.ObsCloseCode == OBSWebsocketDotNet.Communication.ObsCloseCodes.AuthenticationFailed) { MessageBox.Show("Authentication failed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } else if (e.WebsocketDisconnectionInfo != null) { if (e.WebsocketDisconnectionInfo.Exception != null) { MessageBox.Show($"Connection failed: CloseCode: {e.ObsCloseCode} Desc: {e.WebsocketDisconnectionInfo?.CloseStatusDescription} Exception:{e.WebsocketDisconnectionInfo?.Exception?.Message}\nType: {e.WebsocketDisconnectionInfo.Type}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } else { MessageBox.Show($"Connection failed: CloseCode: {e.ObsCloseCode} Desc: {e.WebsocketDisconnectionInfo?.CloseStatusDescription}\nType: {e.WebsocketDisconnectionInfo.Type}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } else { MessageBox.Show($"Connection failed: CloseCode: {e.ObsCloseCode}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } })); } private void onCurrentProgramSceneChanged(object sender, ProgramSceneChangedEventArgs args) { BeginInvoke((MethodInvoker)delegate { tbCurrentScene.Text = args.SceneName; }); } private void onSceneCollectionChanged(object sender, CurrentSceneCollectionChangedEventArgs args) { BeginInvoke((MethodInvoker)delegate { tbSceneCol.Text = obs.GetCurrentSceneCollection(); }); } private void onCurrentProfileChanged(object sender, CurrentProfileChangedEventArgs args) { BeginInvoke((MethodInvoker)delegate { tbProfile.Text = obs.GetProfileList().CurrentProfileName; }); } private void onCurrentSceneTransitionChanged(object sender, CurrentSceneTransitionChangedEventArgs args) { BeginInvoke((MethodInvoker)delegate { tbTransition.Text = args.TransitionName; }); } private void onCurrentSceneTransitionDurationChanged(object sender, CurrentSceneTransitionDurationChangedEventArgs args) { BeginInvoke((MethodInvoker)delegate { tbTransitionDuration.Value = args.TransitionDuration; }); } private void onStreamStateChanged(object sender, StreamStateChangedEventArgs args) { string state = ""; switch (args.OutputState.State) { case OutputState.OBS_WEBSOCKET_OUTPUT_STARTING: state = "Stream starting..."; break; case OutputState.OBS_WEBSOCKET_OUTPUT_STARTED: state = "Stop streaming"; break; case OutputState.OBS_WEBSOCKET_OUTPUT_STOPPING: state = "Stream stopping..."; break; case OutputState.OBS_WEBSOCKET_OUTPUT_STOPPED: state = "Start streaming"; break; default: state = "State unknown"; break; } BeginInvoke((MethodInvoker)delegate { btnToggleStreaming.Text = state; }); } private void onRecordStateChanged(object sender, RecordStateChangedEventArgs args) { string state = ""; switch (args.OutputState.State) { case OutputState.OBS_WEBSOCKET_OUTPUT_STARTING: state = "Recording starting..."; break; case OutputState.OBS_WEBSOCKET_OUTPUT_STARTED: case OutputState.OBS_WEBSOCKET_OUTPUT_RESUMED: state = "Stop recording"; break; case OutputState.OBS_WEBSOCKET_OUTPUT_STOPPING: state = "Recording stopping..."; break; case OutputState.OBS_WEBSOCKET_OUTPUT_STOPPED: state = "Start recording"; break; case OutputState.OBS_WEBSOCKET_OUTPUT_PAUSED: state = "(P) Stop recording"; break; default: state = "State unknown"; break; } BeginInvoke((MethodInvoker)delegate { btnToggleRecording.Text = state; }); } private void btnConnect_Click(object sender, EventArgs e) { if (!obs.IsConnected) { System.Threading.Tasks.Task.Run(() => { try { obs.ConnectAsync(txtServerIP.Text, txtServerPassword.Text); } catch (Exception ex) { BeginInvoke((MethodInvoker)delegate { MessageBox.Show("Connect failed : " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; }); } }); } else { obs.Disconnect(); } } private void btnListScenes_Click(object sender, EventArgs e) { var scenes = obs.ListScenes(); tvScenes.Nodes.Clear(); foreach (var scene in scenes) { var node = new TreeNode(scene.Name); var sources = new List(); sources.AddRange(obs.GetSceneItemList(scene.Name)); foreach (var item in sources) { node.Nodes.Add(item.SourceName); } tvScenes.Nodes.Add(node); } } private void btnGetCurrentScene_Click(object sender, EventArgs e) { tbCurrentScene.Text = obs.GetCurrentProgramScene(); } private void btnSetCurrentScene_Click(object sender, EventArgs e) { obs.SetCurrentProgramScene(tbCurrentScene.Text); } private void tvScenes_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node.Level == 0) { tbCurrentScene.Text = e.Node.Text; } } private void btnListSceneCol_Click(object sender, EventArgs e) { var sc = obs.GetSceneCollectionList(); tvSceneCols.Nodes.Clear(); foreach (var sceneCol in sc) { tvSceneCols.Nodes.Add(sceneCol); } } private void btnGetCurrentSceneCol_Click(object sender, EventArgs e) { tbSceneCol.Text = obs.GetCurrentSceneCollection(); } private void btnSetCurrentSceneCol_Click(object sender, EventArgs e) { obs.SetCurrentSceneCollection(tbSceneCol.Text); } private void tvSceneCols_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node.Level == 0) { tbSceneCol.Text = e.Node.Text; } } private void btnListProfiles_Click(object sender, EventArgs e) { var profiles = obs.GetProfileList(); tvProfiles.Nodes.Clear(); foreach (var profile in profiles.Profiles) { tvProfiles.Nodes.Add(profile); } } private void btnGetCurrentProfile_Click(object sender, EventArgs e) { tbProfile.Text = obs.GetProfileList().CurrentProfileName; } private void btnSetCurrentProfile_Click(object sender, EventArgs e) { obs.SetCurrentProfile(tbProfile.Text); } private void tvProfiles_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node.Level == 0) { tbProfile.Text = e.Node.Text; } } private void btnToggleStreaming_Click(object sender, EventArgs e) { obs.ToggleStream(); } private void btnToggleRecording_Click(object sender, EventArgs e) { obs.ToggleRecord(); } private void btnListTransitions_Click(object sender, EventArgs e) { var transitions = obs.GetSceneTransitionList(); tvTransitions.Nodes.Clear(); foreach (var transition in transitions.Transitions) { tvTransitions.Nodes.Add(transition.Name); } } private void btnGetCurrentTransition_Click(object sender, EventArgs e) { tbTransition.Text = obs.GetCurrentSceneTransition().Name; } private void btnSetCurrentTransition_Click(object sender, EventArgs e) { obs.SetCurrentSceneTransition(tbTransition.Text); } private void tvTransitions_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node.Level == 0) { tbTransition.Text = e.Node.Text; } } private void btnGetTransitionDuration_Click(object sender, EventArgs e) { tbTransitionDuration.Value = obs.GetCurrentSceneTransition().Duration ?? 0; } private void btnSetTransitionDuration_Click(object sender, EventArgs e) { obs.SetCurrentSceneTransitionDuration((int)tbTransitionDuration.Value); } private void btnAdvanced_Click(object sender, EventArgs e) { AdvancedWindow advanced = new AdvancedWindow(); advanced.SetOBS(obs); advanced.Show(); } private void btnBrowse_Click(object sender, EventArgs e) { DialogResult result = this.folderBrowserDialog1.ShowDialog(); if (result == DialogResult.OK) { tbFolderPath.Text = this.folderBrowserDialog1.SelectedPath; } } private void btnSetPath_Click(object sender, EventArgs e) { // TODO: Need a method here, or the button must be removed //obs.SetRecordingFolder(tbFolderPath.Text); } private void onVirtualCamStateChanged(object sender, VirtualcamStateChangedEventArgs args) { string state = ""; switch (args.OutputState.State) { case OutputState.OBS_WEBSOCKET_OUTPUT_STARTING: state = "VirtualCam starting..."; break; case OutputState.OBS_WEBSOCKET_OUTPUT_STARTED: state = "VirtualCam Started"; break; case OutputState.OBS_WEBSOCKET_OUTPUT_STOPPING: state = "VirtualCam stopping..."; break; case OutputState.OBS_WEBSOCKET_OUTPUT_STOPPED: state = "VirtualCam Stopped"; break; default: state = "State unknown"; break; } BeginInvoke((MethodInvoker)delegate { lblVirtualCamStatus.Text = state; }); } private void btnVirtualCamStart_Click(object sender, EventArgs e) { obs.StartVirtualCam(); } private void btnVirtualCamStop_Click(object sender, EventArgs e) { obs.StopVirtualCam(); } private void btnVirtualCamToggle_Click(object sender, EventArgs e) { obs.ToggleVirtualCam(); } private void UpdateOBSStats(ObsStats data) { BeginInvoke((MethodInvoker)delegate { lblRendered.Text = $"{data.RenderTotalFrames} frames"; lblMissed.Text = $"{data.RenderMissedFrames} frames"; lblOutputTotal.Text = $"{data.OutputTotalFrames} frames"; lblSkipped.Text = $"{data.OutputSkippedFrames} frames"; lblAvgRender.Text = $"{data.AverageFrameTime:F2} ms"; lblFPS.Text = $"{(int)data.FPS}"; lblCPU.Text = $"{data.CpuUsage:F2}%"; lblMemory.Text = $"{data.MemoryUsage:F2} MB"; lblDisk.Text = $"{data.FreeDiskSpace:F2} MB"; lblIncomingMessages.Text = $"{data.SessionIncomingMessages}"; lblOutgoingMessages.Text = $"{data.SessionOutgoingMessages}"; }); } private void UpdateStreamStats(OutputStatus data) { BeginInvoke((MethodInvoker)delegate { lblStreamActive.Text = $"{(data.IsActive ? "True" : "False")}"; lblStreamReconnect.Text = $"{(data.IsReconnecting? "True" : "False")}"; lblStreamTimeCode.Text = $"{data.TimeCode}"; lblStreamDuration.Text = $"{data.Duration} ms"; lblStreamCongestion.Text = $"{data.Congestion:F2}"; lblStreamTotalFrames.Text = $"{data.TotalFrames} frames"; lblStreamSkippedFrames.Text = $"{data.SkippedFrames} frames"; lblStreamOutputBytes.Text = $"{data.BytesSent} bytes"; }); } private void UpdateRecordingStats(RecordingStatus data) { BeginInvoke((MethodInvoker)delegate { lblRecording.Text = $"{(data.IsRecording ? "True" : "False")}"; lblRecordingPaused.Text = $"{(data.IsRecordingPaused ? "True" : "False")}"; lblRecordingTimeCode.Text = $"{data.RecordTimecode}"; lblRecordingDuration.Text = $"{data.RecordingDuration} ms"; lblRecordingBytes.Text = $"{data.RecordingBytes:F2} bytes"; }); } private void tableLayoutPanel3_Paint(object sender, PaintEventArgs e) { } private void label17_Click(object sender, EventArgs e) { } private void MainWindow_Load(object sender, EventArgs e) { // Add the event handler for handling UI thread exceptions to the event. Application.ThreadException += Application_ThreadException; // Add the event handler for handling non-UI thread exceptions to the event. AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; } private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { MessageBox.Show($"{((Exception)e.ExceptionObject).Message}", "Unhandled Exception", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } private void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { MessageBox.Show($"{((Exception)e.Exception).Message}", "Unhandled Exception", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } private void btnPauseRecording_Click(object sender, EventArgs e) { obs.PauseRecord(); } } } ================================================ FILE: TestClient/MainWindow.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 17, 17 87, 17 291, 17 25 ================================================ FILE: TestClient/Program.cs ================================================ /* TestClient for obs-websocket-dotnet Copyright (C) 2021 Stéphane Lepin, BarRaider This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see */ using System; using System.Windows.Forms; namespace TestClient { static class Program { /// /// Application entry point /// [STAThread] static void Main() { // Set the unhandled exception mode to force all Windows Forms errors // to go through our handler. Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainWindow()); } } } ================================================ FILE: TestClient/Properties/Resources.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace TestClient.Properties { using System; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TestClient.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } } } ================================================ FILE: TestClient/Properties/Resources.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: TestClient/Properties/Settings.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace TestClient.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); public static Settings Default { get { return defaultInstance; } } } } ================================================ FILE: TestClient/Properties/Settings.settings ================================================  ================================================ FILE: TestClient/TestClient.csproj ================================================  WinExe net9.0-windows7.0 TestClient TestClient 8 true ================================================ FILE: TestClient/packages.config ================================================  ================================================ FILE: obs-websocket-dotnet/Communication/MessageFactory.cs ================================================ using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Text; namespace OBSWebsocketDotNet.Communication { internal static class MessageFactory { internal static JObject BuildMessage(MessageTypes opCode, string messageType, JObject additionalFields, out string messageId) { messageId = Guid.NewGuid().ToString(); JObject payload = new JObject() { { "op", (int)opCode } }; JObject data = new JObject(); switch (opCode) { case MessageTypes.Request: data.Add("requestType", messageType); data.Add("requestId", messageId); data.Add("requestData", additionalFields); additionalFields = null; break; case MessageTypes.RequestBatch: data.Add("requestId", messageId); break; } if (additionalFields != null) { data.Merge(additionalFields); } payload.Add("d", data); return payload; } } } ================================================ FILE: obs-websocket-dotnet/Communication/MessageTypes.cs ================================================ using System; using System.Collections.Generic; using System.Text; namespace OBSWebsocketDotNet.Communication { internal enum MessageTypes { Hello = 0, Identify = 1, Identified = 2, ReIdentify = 3, Event = 5, Request = 6, RequestResponse = 7, RequestBatch = 8, RequestBatchResponse = 9 } } ================================================ FILE: obs-websocket-dotnet/Communication/OBSAuthInfo.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Communication { /// /// Data required by authentication /// public class OBSAuthInfo { /// /// Authentication challenge /// [JsonProperty(PropertyName = "challenge")] public readonly string Challenge; /// /// Password salt /// [JsonProperty(PropertyName = "salt")] public readonly string PasswordSalt; /// /// Builds the object from JSON response body /// /// JSON response body as a public OBSAuthInfo(JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Default Constructor for deserialization /// public OBSAuthInfo() { } } } ================================================ FILE: obs-websocket-dotnet/Communication/ObsCloseCodes.cs ================================================ using System; using System.Collections.Generic; using System.Text; namespace OBSWebsocketDotNet.Communication { /// /// Close/Error codes sent by OBS Websocket when closing the connection /// public enum ObsCloseCodes { /// /// For internal use only to tell the request handler not to perform any close action. /// DontClose = 0, /// /// Unknown reason, should never be used. /// UnknownReason = 4000, /// /// The server was unable to decode the incoming websocket message. /// MessageDecodeError = 4002, /// /// A data field is required but missing from the payload. /// MissingDataField = 4003, /// /// A data field's value type is invalid. /// InvalidDataFieldType = 4004, /// /// A data field's value is invalid. /// InvalidDataFieldValue = 4005, /// /// The specified op was invalid or missing. /// UnknownOpCode = 4006, /// /// The client sent a websocket message without first sending Identify message. /// NotIdentified = 4007, /// /// The client sent an Identify message while already identified. /// AlreadyIdentified = 4008, /// /// The authentication attempt (via Identify) failed. /// AuthenticationFailed = 4009, /// /// The server detected the usage of an old version of the obs-websocket RPC protocol. /// UnsupportedRpcVersion = 4010, /// /// The websocket session has been invalidated by the obs-websocket server. /// SessionInvalidated = 4011, /// /// A requested feature is not supported due to hardware/software limitations. /// UnsupportedFeature = 4012 } } ================================================ FILE: obs-websocket-dotnet/Communication/ObsDisconnectionInfo.cs ================================================ using System; using System.Collections.Generic; using System.Text; using Websocket.Client; namespace OBSWebsocketDotNet.Communication { /// /// Disconnection information received from the OBS Websocket server /// public class ObsDisconnectionInfo { /// /// Close/Error codes sent by OBS Websocket when closing the connection /// public ObsCloseCodes ObsCloseCode { get; private set; } /// /// String reason of disconnect /// public string DisconnectReason { get; set; } /// /// Websocket Client internal information /// public Websocket.Client.DisconnectionInfo WebsocketDisconnectionInfo { get; private set; } /// /// Constructor /// /// Close/Error codes sent by OBS Websocket when closing the connection /// String reason of disconnect /// Websocket Client internal information public ObsDisconnectionInfo(ObsCloseCodes obsCloseCode, string disconnectReason, DisconnectionInfo websocketDisconnectionInfo) { ObsCloseCode = obsCloseCode; DisconnectReason = disconnectReason; WebsocketDisconnectionInfo = websocketDisconnectionInfo; } } } ================================================ FILE: obs-websocket-dotnet/Communication/ServerMessage.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Communication { /// /// Message received from the server /// internal class ServerMessage { /// /// Server Message's operation code /// [JsonProperty(PropertyName = "op")] public MessageTypes OperationCode { set; get; } /// /// Server Data /// [JsonProperty(PropertyName = "d")] public JObject Data { get; set; } } } ================================================ FILE: obs-websocket-dotnet/Events.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OBSWebsocketDotNet.Communication; using OBSWebsocketDotNet.Types; using System; using System.Collections.Generic; using System.Diagnostics; using OBSWebsocketDotNet.Types.Events; using Microsoft.Extensions.Logging; namespace OBSWebsocketDotNet { public partial class OBSWebsocket { #region Events /// /// The current program scene has changed. /// public event EventHandler CurrentProgramSceneChanged; /// /// The list of scenes has changed. /// TODO: Make OBS fire this event when scenes are reordered. /// public event EventHandler SceneListChanged; /// /// Triggered when the scene item list of the specified scene is reordered /// public event EventHandler SceneItemListReindexed; /// /// Triggered when a new item is added to the item list of the specified scene /// public event EventHandler SceneItemCreated; /// /// Triggered when an item is removed from the item list of the specified scene /// public event EventHandler SceneItemRemoved; /// /// Triggered when the visibility of a scene item changes /// public event EventHandler SceneItemEnableStateChanged; /// /// Triggered when the lock status of a scene item changes /// public event EventHandler SceneItemLockStateChanged; /// /// Triggered when switching to another scene collection /// public event EventHandler CurrentSceneCollectionChanged; /// /// Triggered when a scene collection is created, deleted or renamed /// public event EventHandler SceneCollectionListChanged; /// /// Triggered when switching to another transition /// public event EventHandler CurrentSceneTransitionChanged; /// /// Triggered when the current transition duration is changed /// public event EventHandler CurrentSceneTransitionDurationChanged; /// /// Triggered when a transition between two scenes starts. Followed by /// public event EventHandler SceneTransitionStarted; /// /// Triggered when a transition (other than "cut") has ended. Please note that the from-scene field is not available in TransitionEnd /// public event EventHandler SceneTransitionEnded; /// /// Triggered when a stinger transition has finished playing its video /// public event EventHandler SceneTransitionVideoEnded; /// /// Triggered when switching to another profile /// public event EventHandler CurrentProfileChanged; /// /// Triggered when a profile is created, imported, removed or renamed /// public event EventHandler ProfileListChanged; /// /// Triggered when the streaming output state changes /// public event EventHandler StreamStateChanged; /// /// Triggered when the recording output state changes /// public event EventHandler RecordStateChanged; /// /// Triggered when state of the replay buffer changes /// public event EventHandler ReplayBufferStateChanged; /// /// Triggered when the preview scene selection changes (Studio Mode only) /// public event EventHandler CurrentPreviewSceneChanged; /// /// Triggered when Studio Mode is turned on or off /// public event EventHandler StudioModeStateChanged; /// /// Triggered when OBS exits /// public event EventHandler ExitStarted; /// /// Triggered when connected successfully to an obs-websocket server /// public event EventHandler Connected; /// /// Triggered when disconnected from an obs-websocket server /// public event EventHandler Disconnected; /// /// A scene item is selected in the UI /// public event EventHandler SceneItemSelected; /// /// A scene item transform has changed /// public event EventHandler SceneItemTransformChanged; /// /// The audio sync offset of an input has changed /// public event EventHandler InputAudioSyncOffsetChanged; /// /// A filter was added to a source /// public event EventHandler SourceFilterCreated; /// /// A filter was removed from a source /// public event EventHandler SourceFilterRemoved; /// /// Filters in a source have been reordered /// public event EventHandler SourceFilterListReindexed; /// /// Triggered when the visibility of a filter has changed /// public event EventHandler SourceFilterEnableStateChanged; /// /// A source has been muted or unmuted /// public event EventHandler InputMuteStateChanged; /// /// The volume of a source has changed /// public event EventHandler InputVolumeChanged; /// /// A custom broadcast message was received /// public event EventHandler VendorEvent; /// /// These events are emitted by the OBS sources themselves. For example when the media file ends. The behavior depends on the type of media source being used. /// public event EventHandler MediaInputPlaybackEnded; /// /// These events are emitted by the OBS sources themselves. For example when the media file starts playing. The behavior depends on the type of media source being used. /// public event EventHandler MediaInputPlaybackStarted; /// /// This event is only emitted when something actively controls the media/VLC source. In other words, the source will never emit this on its own naturally. /// public event EventHandler MediaInputActionTriggered; /// /// The virtual cam state has changed. /// public event EventHandler VirtualcamStateChanged; /// /// The current scene collection has begun changing. /// public event EventHandler CurrentSceneCollectionChanging; /// /// The current profile has begun changing. /// public event EventHandler CurrentProfileChanging; /// /// The name of a source filter has changed. /// public event EventHandler SourceFilterNameChanged; /// /// An input has been created. /// public event EventHandler InputCreated; /// /// An input has been removed. /// public event EventHandler InputRemoved; /// /// The name of an input has changed. /// public event EventHandler InputNameChanged; /// /// An input's active state has changed. /// When an input is active, it means it's being shown by the program feed. /// public event EventHandler InputActiveStateChanged; /// /// An input's show state has changed. /// When an input is showing, it means it's being shown by the preview or a dialog. /// public event EventHandler InputShowStateChanged; /// /// The audio balance value of an input has changed. /// public event EventHandler InputAudioBalanceChanged; /// /// The audio tracks of an input have changed. /// public event EventHandler InputAudioTracksChanged; /// /// The monitor type of an input has changed. /// Available types are: /// - `OBS_MONITORING_TYPE_NONE` /// - `OBS_MONITORING_TYPE_MONITOR_ONLY` /// - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` /// public event EventHandler InputAudioMonitorTypeChanged; /// /// A high-volume event providing volume levels of all active inputs every 50 milliseconds. /// public event EventHandler InputVolumeMeters; /// /// The replay buffer has been saved. /// public event EventHandler ReplayBufferSaved; /// /// A new scene has been created. /// public event EventHandler SceneCreated; /// /// A scene has been removed. /// public event EventHandler SceneRemoved; /// /// The name of a scene has changed. /// public event EventHandler SceneNameChanged; /// /// An unsupported event has been received. /// public event EventHandler UnsupportedEvent; #endregion #region EventProcessing /// /// Update message handler /// /// Value of "event-type" in the JSON body /// full JSON message body protected void ProcessEventType(string eventType, JObject body) { body = (JObject)body["eventData"]; switch (eventType) { case nameof(CurrentProgramSceneChanged): CurrentProgramSceneChanged?.Invoke(this, new ProgramSceneChangedEventArgs((string)body["sceneName"])); break; case nameof(SceneListChanged): SceneListChanged?.Invoke(this, new SceneListChangedEventArgs(JsonConvert.DeserializeObject>((string)body["scenes"]))); break; case nameof(SceneItemListReindexed): SceneItemListReindexed?.Invoke(this, new SceneItemListReindexedEventArgs((string)body["sceneName"], JsonConvert.DeserializeObject>((string)body["sceneItems"]))); break; case nameof(SceneItemCreated): SceneItemCreated?.Invoke(this, new SceneItemCreatedEventArgs((string)body["sceneName"], (string)body["sourceName"], (int)body["sceneItemId"], (int)body["sceneItemIndex"])); break; case nameof(SceneItemRemoved): SceneItemRemoved?.Invoke(this, new SceneItemRemovedEventArgs((string)body["sceneName"], (string)body["sourceName"], (int)body["sceneItemId"])); break; case nameof(SceneItemEnableStateChanged): SceneItemEnableStateChanged?.Invoke(this, new SceneItemEnableStateChangedEventArgs((string)body["sceneName"], (int)body["sceneItemId"], (bool)body["sceneItemEnabled"])); break; case nameof(SceneItemLockStateChanged): SceneItemLockStateChanged?.Invoke(this, new SceneItemLockStateChangedEventArgs((string)body["sceneName"], (int)body["sceneItemId"], (bool)body["sceneItemLocked"])); break; case nameof(CurrentSceneCollectionChanged): CurrentSceneCollectionChanged?.Invoke(this, new CurrentSceneCollectionChangedEventArgs((string)body["sceneCollectionName"])); break; case nameof(SceneCollectionListChanged): SceneCollectionListChanged?.Invoke(this, new SceneCollectionListChangedEventArgs(JsonConvert.DeserializeObject>((string)body["sceneCollections"]))); break; case nameof(CurrentSceneTransitionChanged): CurrentSceneTransitionChanged?.Invoke(this, new CurrentSceneTransitionChangedEventArgs((string)body["transitionName"])); break; case nameof(CurrentSceneTransitionDurationChanged): CurrentSceneTransitionDurationChanged?.Invoke(this, new CurrentSceneTransitionDurationChangedEventArgs((int)body["transitionDuration"])); break; case nameof(SceneTransitionStarted): SceneTransitionStarted?.Invoke(this, new SceneTransitionStartedEventArgs((string)body["transitionName"])); break; case nameof(SceneTransitionEnded): SceneTransitionEnded?.Invoke(this, new SceneTransitionEndedEventArgs((string)body["transitionName"])); break; case nameof(SceneTransitionVideoEnded): SceneTransitionVideoEnded?.Invoke(this, new SceneTransitionVideoEndedEventArgs((string)body["transitionName"])); break; case nameof(CurrentProfileChanged): CurrentProfileChanged?.Invoke(this, new CurrentProfileChangedEventArgs((string)body["profileName"])); break; case nameof(ProfileListChanged): ProfileListChanged?.Invoke(this, new ProfileListChangedEventArgs(JsonConvert.DeserializeObject>((string)body["profiles"]))); break; case nameof(StreamStateChanged): StreamStateChanged?.Invoke(this, new StreamStateChangedEventArgs(new OutputStateChanged(body))); break; case nameof(RecordStateChanged): RecordStateChanged?.Invoke(this, new RecordStateChangedEventArgs(new RecordStateChanged(body))); break; case nameof(CurrentPreviewSceneChanged): CurrentPreviewSceneChanged?.Invoke(this, new CurrentPreviewSceneChangedEventArgs((string)body["sceneName"])); break; case nameof(StudioModeStateChanged): StudioModeStateChanged?.Invoke(this, new StudioModeStateChangedEventArgs((bool)body["studioModeEnabled"])); break; case nameof(ReplayBufferStateChanged): ReplayBufferStateChanged?.Invoke(this, new ReplayBufferStateChangedEventArgs(new OutputStateChanged(body))); break; case nameof(ExitStarted): ExitStarted?.Invoke(this, EventArgs.Empty); break; case nameof(SceneItemSelected): SceneItemSelected?.Invoke(this, new SceneItemSelectedEventArgs((string)body["sceneName"], (string)body["sceneItemId"])); break; case nameof(SceneItemTransformChanged): SceneItemTransformChanged?.Invoke(this, new SceneItemTransformEventArgs((string)body["sceneName"], (string)body["sceneItemId"], new SceneItemTransformInfo((JObject)body["sceneItemTransform"]))); break; case nameof(InputAudioSyncOffsetChanged): InputAudioSyncOffsetChanged?.Invoke(this, new InputAudioSyncOffsetChangedEventArgs((string)body["inputName"], (int)body["inputAudioSyncOffset"])); break; case nameof(InputMuteStateChanged): InputMuteStateChanged?.Invoke(this, new InputMuteStateChangedEventArgs((string)body["inputName"], (bool)body["inputMuted"])); break; case nameof(InputVolumeChanged): InputVolumeChanged?.Invoke(this, new InputVolumeChangedEventArgs(new InputVolume(body))); break; case nameof(SourceFilterCreated): 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 nameof(SourceFilterRemoved): SourceFilterRemoved?.Invoke(this, new SourceFilterRemovedEventArgs((string)body["sourceName"], (string)body["filterName"])); break; case nameof(SourceFilterListReindexed): if (SourceFilterListReindexed != null) { List filters = new List(); JsonConvert.PopulateObject(body["filters"].ToString(), filters); SourceFilterListReindexed?.Invoke(this, new SourceFilterListReindexedEventArgs((string)body["sourceName"], filters)); } break; case nameof(SourceFilterEnableStateChanged): SourceFilterEnableStateChanged?.Invoke(this, new SourceFilterEnableStateChangedEventArgs((string)body["sourceName"], (string)body["filterName"], (bool)body["filterEnabled"])); break; case nameof(VendorEvent): VendorEvent?.Invoke(this, new VendorEventArgs((string)body["vendorName"], (string)body["eventType"], body)); break; case nameof(MediaInputPlaybackEnded): MediaInputPlaybackEnded?.Invoke(this, new MediaInputPlaybackEndedEventArgs((string)body["inputName"])); break; case nameof(MediaInputPlaybackStarted): MediaInputPlaybackStarted?.Invoke(this, new MediaInputPlaybackStartedEventArgs((string)body["sourceName"])); break; case nameof(MediaInputActionTriggered): MediaInputActionTriggered?.Invoke(this, new MediaInputActionTriggeredEventArgs((string)body["inputName"], (string)body["mediaAction"])); break; case nameof(VirtualcamStateChanged): VirtualcamStateChanged?.Invoke(this, new VirtualcamStateChangedEventArgs(new OutputStateChanged(body))); break; case nameof(CurrentSceneCollectionChanging): CurrentSceneCollectionChanging?.Invoke(this, new CurrentSceneCollectionChangingEventArgs((string)body["sceneCollectionName"])); break; case nameof(CurrentProfileChanging): CurrentProfileChanging?.Invoke(this, new CurrentProfileChangingEventArgs((string)body["profileName"])); break; case nameof(SourceFilterNameChanged): SourceFilterNameChanged?.Invoke(this, new SourceFilterNameChangedEventArgs((string)body["sourceName"], (string)body["oldFilterName"], (string)body["filterName"])); break; case nameof(InputCreated): InputCreated?.Invoke(this, new InputCreatedEventArgs((string)body["inputName"], (string)body["inputKind"], (string)body["unversionedInputKind"], (JObject)body["inputSettings"], (JObject)body["defaultInputSettings"])); break; case nameof(InputRemoved): InputRemoved?.Invoke(this, new InputRemovedEventArgs((string)body["inputName"])); break; case nameof(InputNameChanged): InputNameChanged?.Invoke(this, new InputNameChangedEventArgs((string)body["oldInputName"], (string)body["inputName"])); break; case nameof(InputActiveStateChanged): InputActiveStateChanged?.Invoke(this, new InputActiveStateChangedEventArgs((string)body["inputName"], (bool)body["videoActive"])); break; case nameof(InputShowStateChanged): InputShowStateChanged?.Invoke(this, new InputShowStateChangedEventArgs((string)body["inputName"], (bool)body["videoShowing"])); break; case nameof(InputAudioBalanceChanged): InputAudioBalanceChanged?.Invoke(this, new InputAudioBalanceChangedEventArgs((string)body["inputName"], (double)body["inputAudioBalance"])); break; case nameof(InputAudioTracksChanged): InputAudioTracksChanged?.Invoke(this, new InputAudioTracksChangedEventArgs((string)body["inputName"], (JObject)body["inputAudioTracks"])); break; case nameof(InputAudioMonitorTypeChanged): InputAudioMonitorTypeChanged?.Invoke(this, new InputAudioMonitorTypeChangedEventArgs((string)body["inputName"], (string)body["monitorType"])); break; case nameof(InputVolumeMeters): InputVolumeMeters?.Invoke(this, new InputVolumeMetersEventArgs(JsonConvert.DeserializeObject>((string)body["inputs"]))); break; case nameof(ReplayBufferSaved): ReplayBufferSaved?.Invoke(this, new ReplayBufferSavedEventArgs((string)body["savedReplayPath"])); break; case nameof(SceneCreated): SceneCreated?.Invoke(this, new SceneCreatedEventArgs((string)body["sceneName"], (bool)body["isGroup"])); break; case nameof(SceneRemoved): SceneRemoved?.Invoke(this, new SceneRemovedEventArgs((string)body["sceneName"], (bool)body["isGroup"])); break; case nameof(SceneNameChanged): SceneNameChanged?.Invoke(this, new SceneNameChangedEventArgs((string)body["oldSceneName"], (string)body["sceneName"])); break; default: var message = $"Unsupported Event: {eventType}\n{body}"; Logger?.LogInformation(message); UnsupportedEvent?.Invoke(this, new UnsupportedEventArgs(eventType, body)); break; } } #endregion } } ================================================ FILE: obs-websocket-dotnet/Exceptions.cs ================================================ using System; namespace OBSWebsocketDotNet { /// /// Thrown if authentication fails /// public class AuthFailureException : Exception { } /// /// Thrown when the server responds with an error /// public class ErrorResponseException : Exception { /// /// Error Code of exception /// public int ErrorCode { get; set; } /// /// Constructor /// /// Exception Message /// /// Error Code public ErrorResponseException(string message, int errorCode) : base(message) { ErrorCode = errorCode; } } } ================================================ FILE: obs-websocket-dotnet/IOBSWebsocket.cs ================================================ using System; using System.Collections.Generic; using Newtonsoft.Json.Linq; using OBSWebsocketDotNet.Communication; using OBSWebsocketDotNet.Types; using OBSWebsocketDotNet.Types.Events; using Websocket.Client; namespace OBSWebsocketDotNet { /// /// OBS Websocket Dotnet interface /// public interface IOBSWebsocket { #region Properties /// /// WebSocket request timeout, represented as a TimeSpan object /// TimeSpan WSTimeout { get; set; } /// /// Current connection state /// bool IsConnected { get; } #endregion #region Requests /// /// Get basic OBS video information /// ObsVideoSettings GetVideoSettings(); /// /// Saves a screenshot of a source to the filesystem. /// The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. /// If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. /// **Compatible with inputs and scenes.** /// /// Name of the source to take a screenshot of /// Image compression format to use. Use `GetVersion` to get compatible image formats /// Path to save the screenshot file to. Eg. `C:\\Users\\user\\Desktop\\screenshot.png` /// Width to scale the screenshot to /// Height to scale the screenshot to /// Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use \"default\" (whatever that means, idk) /// Base64-encoded screenshot string string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1); /// /// Saves a screenshot of a source to the filesystem. /// The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. /// If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. /// **Compatible with inputs and scenes.** /// /// Name of the source to take a screenshot of /// Image compression format to use. Use `GetVersion` to get compatible image formats /// Path to save the screenshot file to. Eg. `C:\\Users\\user\\Desktop\\screenshot.png` /// Base64-encoded screenshot string string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath); /// /// Executes hotkey routine, identified by hotkey unique name /// /// Unique name of the hotkey, as defined when registering the hotkey (e.g. "ReplayBuffer.Save") void TriggerHotkeyByName(string hotkeyName); /// /// Triggers a hotkey using a sequence of keys. /// /// Main key identifier (e.g. OBS_KEY_A for key "A"). Available identifiers are here: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-hotkeys.h /// Optional key modifiers object. You can combine multiple key operators. e.g. KeyModifier.Shift | KeyModifier.Control void TriggerHotkeyByKeySequence(OBSHotkey keyId, KeyModifier keyModifier = KeyModifier.None); /// /// Get the name of the currently active scene. /// /// Name of the current scene string GetCurrentProgramScene(); /// /// Set the current scene to the specified one /// /// The desired scene name void SetCurrentProgramScene(string sceneName); /// /// Get OBS stats (almost the same info as provided in OBS' stats window) /// ObsStats GetStats(); /// /// List every available scene /// /// A of objects describing each scene List ListScenes(); /// /// Get a list of scenes in the currently active profile /// GetSceneListInfo GetSceneList(); /// /// Get the specified scene's transition override info /// /// Name of the scene to return the override info /// TransitionOverrideInfo TransitionOverrideInfo GetSceneSceneTransitionOverride(string sceneName); /// /// Set specific transition override for a scene /// /// Name of the scene to set the transition override /// Name of the transition to use /// Duration in milliseconds of the transition if transition is not fixed. Defaults to the current duration specified in the UI if there is no current override and this value is not given void SetSceneSceneTransitionOverride(string sceneName, string transitionName, int transitionDuration = -1); /// /// If your code needs to perform multiple successive T-Bar moves (e.g. : in an animation, or in response to a user moving a T-Bar control in your User Interface), set release to false and call ReleaseTBar later once the animation/interaction is over. /// /// T-Bar position. This value must be between 0.0 and 1.0. /// Whether or not the T-Bar gets released automatically after setting its new position (like a user releasing their mouse button after moving the T-Bar). Call ReleaseTBar manually if you set release to false. Defaults to true. void SetTBarPosition(double position, bool release = true); /// /// Apply settings to a source filter /// /// Source with filter /// Filter name /// JObject with filter settings /// Apply over existing settings? void SetSourceFilterSettings(string sourceName, string filterName, JObject filterSettings, bool overlay = false); /// /// Apply settings to a source filter /// /// Source with filter /// Filter name /// Filter settings /// Apply over existing settings? void SetSourceFilterSettings(string sourceName, string filterName, FilterSettings filterSettings, bool overlay = false); /// /// Modify the Source Filter's visibility /// /// Source name /// Source filter name /// New filter state void SetSourceFilterEnabled(string sourceName, string filterName, bool filterEnabled); /// /// Return a list of all filters on a source /// /// Source name List GetSourceFilterList(string sourceName); /// /// Return a list of settings for a specific filter /// /// Source name /// Filter name FilterSettings GetSourceFilter(string sourceName, string filterName); /// /// Remove the filter from a source /// /// Name of the source the filter is on /// Name of the filter to remove bool RemoveSourceFilter(string sourceName, string filterName); /// /// Add a filter to a source /// /// Name of the source for the filter /// Name of the filter /// Type of filter /// JObject holding filter settings object void CreateSourceFilter(string sourceName, string filterName, string filterKind, JObject filterSettings); /// /// Add a filter to a source /// /// Name of the source for the filter /// Name of the filter /// Type of filter /// Filter settings object void CreateSourceFilter(string sourceName, string filterName, string filterKind, FilterSettings filterSettings); /// /// Toggles the status of the stream output. /// /// New state of the stream output bool ToggleStream(); /// /// Toggles the status of the record output. /// void ToggleRecord(); /// /// Gets the status of the stream output /// /// An object describing the current outputs states OutputStatus GetStreamStatus(); /// /// Get the current transition name and duration /// /// An object with the current transition name and duration TransitionSettings GetCurrentSceneTransition(); /// /// Set the current transition to the specified one /// /// Desired transition name void SetCurrentSceneTransition(string transitionName); /// /// Change the transition's duration /// /// Desired transition duration (in milliseconds) void SetCurrentSceneTransitionDuration(int transitionDuration); /// /// Change the current settings of a transition /// /// Transition settings (they can be partial) /// Whether to overlay over the current settins or replace them /// Updated transition settings void SetCurrentSceneTransitionSettings(JObject transitionSettings, bool overlay); /// /// Change the volume of the specified source /// /// Name of the source which volume will be changed /// Desired volume. Must be between `0.0` and `1.0` for amplitude/mul (useDecibel is false), and under 0.0 for dB (useDecibel is true). Note: OBS will interpret dB values under -100.0 as Inf. /// Interperet `volume` data as decibels instead of amplitude/mul. void SetInputVolume(string inputName, float inputVolume, bool inputVolumeDb = false); /// /// Get the volume of the specified source /// Volume is between `0.0` and `1.0` if using amplitude/mul (useDecibel is false), under `0.0` if using dB (useDecibel is true). /// /// Source name /// An Object containing the volume and mute state of the specified source. VolumeInfo GetInputVolume(string inputName); /// /// Gets the audio mute state of an input. /// /// Name of input to get the mute state of /// Whether the input is muted bool GetInputMute(string inputName); /// /// Set the mute state of the specified source /// /// Name of the source which mute state will be changed /// Desired mute state void SetInputMute(string inputName, bool inputMuted); /// /// Toggle the mute state of the specified source /// /// Name of the source which mute state will be toggled void ToggleInputMute(string inputName); /// /// Sets the transform and crop info of a scene item /// /// Name of the scene that has the SceneItem /// Id of the Scene Item /// JObject holding transform settings void SetSceneItemTransform(string sceneName, int sceneItemId, JObject sceneItemTransform); /// /// Sets the transform and crop info of a scene item /// /// Name of the scene that has the SceneItem /// Id of the Scene Item /// Transform settings void SetSceneItemTransform(string sceneName, int sceneItemId, SceneItemTransformInfo sceneItemTransform); /// /// Set the current scene collection to the specified one /// /// Desired scene collection name void SetCurrentSceneCollection(string sceneCollectionName); /// /// Get the name of the current scene collection /// /// Name of the current scene collection string GetCurrentSceneCollection(); /// /// List all scene collections /// /// A of the names of all scene collections List GetSceneCollectionList(); /// /// Set the current profile to the specified one /// /// Name of the desired profile void SetCurrentProfile(string profileName); /// /// List all profiles /// /// A of the names of all profiles GetProfileListInfo GetProfileList(); /// /// Start streaming. Will trigger an error if streaming is already active /// void StartStream(); /// /// Stop streaming. Will trigger an error if streaming is not active. /// void StopStream(); /// /// Start recording. Will trigger an error if recording is already active. /// void StartRecord(); /// /// Stop recording. Will trigger an error if recording is not active. /// File name for the saved recording /// string StopRecord(); /// /// Pause the current recording. Returns an error if recording is not active or already paused. /// void PauseRecord(); /// /// Resume/unpause the current recording (if paused). Returns an error if recording is not active or not paused. /// void ResumeRecord(); /// /// Get the path of the current recording folder /// /// Current recording folder path string GetRecordDirectory(); /// /// Get current recording status. /// /// RecordingStatus GetRecordStatus(); /// /// Get the status of the OBS replay buffer. /// /// Current recording status. true when active bool GetReplayBufferStatus(); /// /// Get duration of the currently selected transition (if supported) /// /// Current transition duration (in milliseconds) GetTransitionListInfo GetSceneTransitionList(); /// /// Get status of Studio Mode /// /// Studio Mode status (on/off) bool GetStudioModeEnabled(); /// /// Enables or disables studio mode /// /// void SetStudioModeEnabled(bool studioModeEnabled); /// /// Get the name of the currently selected preview scene. /// Note: Triggers an error if Studio Mode is disabled /// /// Preview scene name string GetCurrentPreviewScene(); /// /// Change the currently active preview/studio scene to the one specified. /// Triggers an error if Studio Mode is disabled /// /// Preview scene name void SetCurrentPreviewScene(string sceneName); /// /// Change the currently active preview/studio scene to the one specified. /// Triggers an error if Studio Mode is disabled. /// /// Preview scene object void SetCurrentPreviewScene(ObsScene previewScene); /// /// Triggers the current scene transition. Same functionality as the `Transition` button in Studio Mode /// void TriggerStudioModeTransition(); /// /// Toggles the state of the replay buffer output. /// void ToggleReplayBuffer(); /// /// Start recording into the Replay Buffer. Triggers an error /// if the Replay Buffer is already active, or if the "Save Replay Buffer" /// hotkey is not set in OBS' settings /// void StartReplayBuffer(); /// /// Stop recording into the Replay Buffer. Triggers an error if the /// Replay Buffer is not active. /// void StopReplayBuffer(); /// /// Save and flush the contents of the Replay Buffer to disk. Basically /// the same as triggering the "Save Replay Buffer" hotkey in OBS. /// Triggers an error if Replay Buffer is not active. /// void SaveReplayBuffer(); /// /// Set the audio sync offset of the specified source /// /// Source name /// Audio offset (in nanoseconds) for the specified source void SetInputAudioSyncOffset(string inputName, int inputAudioSyncOffset); /// /// Get the audio sync offset of the specified source /// /// Source name /// Audio offset (in nanoseconds) of the specified source int GetInputAudioSyncOffset(string inputName); /// /// Removes a scene item from a scene. /// Scenes only. /// /// Scene item id /// Scene name from which to delete item void RemoveSceneItem(string sceneName, int sceneItemId); /// /// Sends CEA-608 caption text over the stream output. As of OBS Studio 23.1, captions are not yet available on Linux. /// /// Captions text void SendStreamCaption(string captionText); /// /// Duplicates a scene item /// /// Name of the scene that has the SceneItem /// Id of the Scene Item /// Name of scene to add the new duplicated Scene Item. If not specified will assume sceneName void DuplicateSceneItem(string sceneName, int sceneItemId, string destinationSceneName = null); /// /// Gets the names of all special inputs. /// /// Dictionary of special inputs. Dictionary GetSpecialInputs(); /// /// Sets the current stream service settings (stream destination). /// Note: Simple RTMP settings can be set with type `rtmp_custom` and the settings fields `server` and `key`. /// /// Stream Service Type Name and Settings objects void SetStreamServiceSettings(StreamingService service); /// /// Gets the current stream service settings (stream destination). /// /// Stream service type and settings objects StreamingService GetStreamServiceSettings(); /// /// Gets the audio monitor type of an input. /// The available audio monitor types are: /// - `OBS_MONITORING_TYPE_NONE` /// - `OBS_MONITORING_TYPE_MONITOR_ONLY` /// - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` /// /// Source name /// The monitor type in use string GetInputAudioMonitorType(string inputName); /// /// Sets the audio monitor type of an input. /// /// Name of the input to set the audio monitor type of /// Audio monitor type. See `GetInputAudioMonitorType for possible types. void SetInputAudioMonitorType(string inputName, string monitorType); /// /// Broadcasts a `CustomEvent` to all WebSocket clients. Receivers are clients which are identified and subscribed. /// /// Data payload to emit to all receivers void BroadcastCustomEvent(JObject eventData); /// /// Sets the cursor position of a media input. /// This request does not perform bounds checking of the cursor position. /// /// Name of the media input /// New cursor position to set (milliseconds). void SetMediaInputCursor(string inputName, int mediaCursor); /// /// Offsets the current cursor position of a media input by the specified value. /// This request does not perform bounds checking of the cursor position. /// /// Name of the media input /// Value to offset the current cursor position by (milliseconds +/-) void OffsetMediaInputCursor(string inputName, int mediaCursorOffset); /// /// Creates a new input, adding it as a scene item to the specified scene. /// /// Name of the scene to add the input to as a scene item /// Name of the new input to created /// The kind of input to be created /// Jobject holding the settings object to initialize the input with /// Whether to set the created scene item to enabled or disabled /// ID of the SceneItem in the scene. int CreateInput(string sceneName, string inputName, string inputKind, JObject inputSettings, bool? sceneItemEnabled); /// /// Gets the default settings for an input kind. /// /// Input kind to get the default settings for /// Object of default settings for the input kind JObject GetInputDefaultSettings(string inputKind); /// /// Gets a list of all scene items in a scene. /// Scenes only /// /// Name of the scene to get the items of /// Array of scene items in the scene List GetSceneItemList(string sceneName); /// /// Creates a new scene item using a source. /// Scenes only /// /// Name of the scene to create the new item in /// Name of the source to add to the scene /// Enable state to apply to the scene item on creation /// Numeric ID of the scene item int CreateSceneItem(string sceneName, string sourceName, bool sceneItemEnabled = true); /// /// Creates a new scene in OBS. /// /// Name for the new scene void CreateScene(string sceneName); /// /// Gets the enable state of all audio tracks of an input. /// /// Name of the input /// Object of audio tracks and associated enable states SourceTracks GetInputAudioTracks(string inputName); /// /// Sets the enable state of audio tracks of an input. /// /// Name of the input /// JObject holding track settings to apply void SetInputAudioTracks(string inputName, JObject inputAudioTracks); /// /// Sets the enable state of audio tracks of an input. /// /// Name of the input /// Track settings to apply void SetInputAudioTracks(string inputName, SourceTracks inputAudioTracks); /// /// Gets the active and show state of a source. /// **Compatible with inputs and scenes.** /// /// Name of the source to get the active state of /// Whether the source is showing in Program SourceActiveInfo GetSourceActive(string sourceName); /// /// Gets the status of the virtualcam output. /// /// An object describing the current virtual camera state VirtualCamStatus GetVirtualCamStatus(); /// /// Starts the virtualcam output. /// void StartVirtualCam(); /// /// Stops the virtualcam output. /// void StopVirtualCam(); /// /// Toggles the state of the virtualcam output. /// /// Whether the output is active VirtualCamStatus ToggleVirtualCam(); /// /// Gets the value of a \"slot\" from the selected persistent data realm. /// /// The data realm to select. `OBS_WEBSOCKET_DATA_REALM_GLOBAL` or `OBS_WEBSOCKET_DATA_REALM_PROFILE` /// The name of the slot to retrieve data from /// Value associated with the slot. `null` if not set JObject GetPersistentData(string realm, string slotName); /// /// Sets the value of a \"slot\" from the selected persistent data realm. /// /// The data realm to select. `OBS_WEBSOCKET_DATA_REALM_GLOBAL` or `OBS_WEBSOCKET_DATA_REALM_PROFILE` /// The name of the slot to retrieve data from /// The value to apply to the slot void SetPersistentData(string realm, string slotName, JObject slotValue); /// /// Creates a new scene collection, switching to it in the process.\n\nNote: This will block until the collection has finished changing. /// /// Name for the new scene collection void CreateSceneCollection(string sceneCollectionName); /// /// Creates a new profile, switching to it in the process /// /// Name for the new profile void CreateProfile(string profileName); /// /// Removes a profile. If the current profile is chosen, it will change to a different profile first. /// /// Name of the profile to remove void RemoveProfile(string profileName); /// /// Gets a parameter from the current profile's configuration. /// /// Category of the parameter to get /// Name of the parameter to get /// JObject GetProfileParameter(string parameterCategory, string parameterName); /// /// Sets the value of a parameter in the current profile's configuration. /// /// Category of the parameter to set /// Name of the parameter to set /// Value of the parameter to set. Use `null` to delete void SetProfileParameter(string parameterCategory, string parameterName, string parameterValue); /// /// Sets the current video settings. /// Note: Fields must be specified in pairs. For example, you cannot set only `baseWidth` without needing to specify `baseHeight`. /// /// Object containing video settings void SetVideoSettings(ObsVideoSettings obsVideoSettings); /// /// Gets the default settings for a filter kind. /// /// Filter kind to get the default settings for /// Object of default settings for the filter kind JObject GetSourceFilterDefaultSettings(string filterKind); /// /// Sets the name of a source filter (rename). /// /// Name of the source the filter is on /// Current name of the filter /// New name for the filter void SetSourceFilterName(string sourceName, string filterName, string newFilterName); /// /// Sets the index position of a filter on a source. /// /// Name of the source the filter is on /// Name of the filter /// New index position of the filter void SetSourceFilterIndex(string sourceName, string filterName, int filterIndex); /// /// Gets data about the current plugin and RPC version. /// /// Version info in an object ObsVersion GetVersion(); /// /// Call a request registered to a vendor. /// A vendor is a unique name registered by a third-party plugin or script, which allows for custom requests and events to be added to obs-websocket. /// If a plugin or script implements vendor requests or events, documentation is expected to be provided with them. /// /// Name of the vendor to use /// The request type to call /// Object containing appropriate request data /// Object containing appropriate response data. {} if request does not provide any response data JObject CallVendorRequest(string vendorName, string requestType, JObject requestData = null); /// /// Gets an array of all hotkey names in OBS /// /// Array of hotkey names List GetHotkeyList(); /// /// Sleeps for a time duration or number of frames. Only available in request batches with types `SERIAL_REALTIME` or `SERIAL_FRAME`. /// /// Number of milliseconds to sleep for (if `SERIAL_REALTIME` mode) /// Number of frames to sleep for (if `SERIAL_FRAME` mode) void Sleep(int sleepMillis, int sleepFrames); /// /// Gets an array of all inputs in OBS. /// /// Restrict the array to only inputs of the specified kind /// List of Inputs in OBS List GetInputList(string inputKind = null); /// /// Gets an array of all available input kinds in OBS. /// /// True == Return all kinds as unversioned, False == Return with version suffixes (if available) /// Array of input kinds List GetInputKindList(bool unversioned = false); /// /// Removes an existing input. /// Note: Will immediately remove all associated scene items. /// /// Name of the input to remove void RemoveInput(string inputName); /// /// Sets the name of an input (rename). /// /// Current input name /// New name for the input void SetInputName(string inputName, string newInputName); /// /// Gets the settings of an input. /// Note: Does not include defaults. To create the entire settings object, overlay `inputSettings` over the `defaultInputSettings` provided by `GetInputDefaultSettings`. /// /// Name of the input to get the settings of /// New populated InputSettings object InputSettings GetInputSettings(string inputName); /// /// Sets the settings of an input. /// /// Object of settings to apply /// True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. void SetInputSettings(InputSettings inputSettings, bool overlay = true); /// /// Sets the settings of an input. /// /// Name of the input to set the settings of /// Object of settings to apply /// True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. void SetInputSettings(string inputName, JObject inputSettings, bool overlay = true); /// /// Gets the audio balance of an input. /// /// Name of the input to get the audio balance of /// Audio balance value from 0.0-1.0 double GetInputAudioBalance(string inputName); /// /// Sets the audio balance of an input. /// /// Name of the input to set the audio balance of /// New audio balance value void SetInputAudioBalance(string inputName, double inputAudioBalance); /// /// Gets the items of a list property from an input's properties. /// Note: Use this in cases where an input provides a dynamic, selectable list of items. /// For example, display capture, where it provides a list of available displays. /// /// Name of the input /// Name of the list property to get the items of /// Array of items in the list property List GetInputPropertiesListPropertyItems(string inputName, string propertyName); /// /// Presses a button in the properties of an input. /// Note: Use this in cases where there is a button in the properties of an input that cannot be accessed in any other way. /// For example, browser sources, where there is a refresh button. /// /// Name of the input /// Name of the button property to press void PressInputPropertiesButton(string inputName, string propertyName); /// /// Gets the status of a media input.\n\nMedia States: /// - `OBS_MEDIA_STATE_NONE` /// - `OBS_MEDIA_STATE_PLAYING` /// - `OBS_MEDIA_STATE_OPENING` /// - `OBS_MEDIA_STATE_BUFFERING` /// - `OBS_MEDIA_STATE_PAUSED` /// - `OBS_MEDIA_STATE_STOPPED` /// - `OBS_MEDIA_STATE_ENDED` /// - `OBS_MEDIA_STATE_ERROR` /// /// Name of the media input /// Object containing string mediaState, int mediaDuration, int mediaCursor properties MediaInputStatus GetMediaInputStatus(string inputName); /// /// Triggers an action on a media input. /// /// Name of the media input /// Identifier of the `ObsMediaInputAction` enum void TriggerMediaInputAction(string inputName, string mediaAction); /// /// Gets the filename of the last replay buffer save file. /// /// File path of last replay string GetLastReplayBufferReplay(); /// /// Toggles pause on the record output. /// void ToggleRecordPause(); /// /// Currently BROKEN in obs-websocket/obs-studio /// Basically GetSceneItemList, but for groups. /// Using groups at all in OBS is discouraged, as they are very broken under the hood. /// Groups only /// /// Name of the group to get the items of /// Array of scene items in the group List GetGroupSceneItemList(string sceneName); /// /// Searches a scene for a source, and returns its id.\n\nScenes and Groups /// /// Name of the scene or group to search in /// Name of the source to find /// Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item /// Numeric ID of the scene item int GetSceneItemId(string sceneName, string sourceName, int searchOffset); /// /// Gets the transform and crop info of a scene item. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Object containing scene item transform info SceneItemTransformInfo GetSceneItemTransform(string sceneName, int sceneItemId); /// /// Gets the JObject of transform settings for a scene item. Use this one you don't want it populated with default values. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Object containing scene item transform info JObject GetSceneItemTransformRaw(string sceneName, int sceneItemId); /// /// Gets the enable state of a scene item. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Whether the scene item is enabled. `true` for enabled, `false` for disabled bool GetSceneItemEnabled(string sceneName, int sceneItemId); /// /// Gets the enable state of a scene item. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// New enable state of the scene item void SetSceneItemEnabled(string sceneName, int sceneItemId, bool sceneItemEnabled); /// /// Gets the lock state of a scene item. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Whether the scene item is locked. `true` for locked, `false` for unlocked bool GetSceneItemLocked(string sceneName, int sceneItemId); /// /// Sets the lock state of a scene item. /// Scenes and Group /// /// Name of the scene the item is in /// Numeric ID of the scene item /// New lock state of the scene item void SetSceneItemLocked(string sceneName, int sceneItemId, bool sceneItemLocked); /// /// Gets the index position of a scene item in a scene. /// An index of 0 is at the bottom of the source list in the UI. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Index position of the scene item int GetSceneItemIndex(string sceneName, int sceneItemId); /// /// Sets the index position of a scene item in a scene. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// New index position of the scene item void SetSceneItemIndex(string sceneName, int sceneItemId, int sceneItemIndex); /// /// Gets the blend mode of a scene item. /// Blend modes: /// - `OBS_BLEND_NORMAL` /// - `OBS_BLEND_ADDITIVE` /// - `OBS_BLEND_SUBTRACT` /// - `OBS_BLEND_SCREEN` /// - `OBS_BLEND_MULTIPLY` /// - `OBS_BLEND_LIGHTEN` /// - `OBS_BLEND_DARKEN` /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Current blend mode string GetSceneItemBlendMode(string sceneName, int sceneItemId); /// /// Sets the blend mode of a scene item. /// Scenes and Groups /// /// /// /// void SetSceneItemBlendMode(string sceneName, int sceneItemId, string sceneItemBlendMode); /// /// Gets an array of all groups in OBS. /// Groups in OBS are actually scenes, but renamed and modified. In obs-websocket, we treat them as scenes where we can. /// /// Array of group names List GetGroupList(); /// /// Removes a scene from OBS. /// /// Name of the scene to remove void RemoveScene(string sceneName); /// /// Sets the name of a scene (rename). /// /// Name of the scene to be renamed /// New name for the scene void SetSceneName(string sceneName, string newSceneName); /// /// Gets a Base64-encoded screenshot of a source. /// The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. /// If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. /// **Compatible with inputs and scenes.** /// /// Name of the source to take a screenshot of /// Image compression format to use. Use `GetVersion` to get compatible image formats /// Width to scale the screenshot to /// Height to scale the screenshot to /// Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use \"default\" (whatever that means, idk) /// Base64-encoded screenshot string GetSourceScreenshot(string sourceName, string imageFormat, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1); /// /// Gets an array of all available transition kinds. /// Similar to `GetInputKindList` /// /// Array of transition kinds List GetTransitionKindList(); /// /// Gets the cursor position of the current scene transition. /// Note: `transitionCursor` will return 1.0 when the transition is inactive. /// /// Cursor position, between 0.0 and 1.0 double GetCurrentSceneTransitionCursor(); /// /// Opens the properties dialog of an input. /// /// Name of the input to open the dialog of void OpenInputPropertiesDialog(string inputName); /// /// Opens the filters dialog of an input. /// /// Name of the input to open the dialog of void OpenInputFiltersDialog(string inputName); /// /// Opens the interact dialog of an input. /// /// Name of the input to open the dialog of void OpenInputInteractDialog(string inputName); /// /// Gets a list of connected monitors and information about them. /// /// a list of detected monitors with some information List GetMonitorList(); /// /// Connect this instance to the specified URL, and authenticate (if needed) with the specified password. /// NOTE: Please subscribe to the Connected/Disconnected events (or atlease check the IsConnected property) to determine when the connection is actually fully established /// /// Server URL in standard URL format. /// Server password [Obsolete("Please use ConnectAsync, this function will be removed in the next version")] void Connect(string url, string password); /// /// Connect this instance to the specified URL, and authenticate (if needed) with the specified password. /// NOTE: Please subscribe to the Connected/Disconnected events (or atleast check the IsConnected property) to determine when the connection is actually fully established /// /// Server URL in standard URL format. /// Server password void ConnectAsync(string url, string password); /// /// Disconnect this instance from the server /// void Disconnect(); /// /// Sends a message to the websocket API with the specified request type and optional parameters /// /// obs-websocket request type, must be one specified in the protocol specification /// additional JSON fields if required by the request type /// The server's JSON response as a JObject JObject SendRequest(string requestType, JObject additionalFields = null); /// /// Request authentication data. You don't have to call this manually. /// /// Authentication data in an object OBSAuthInfo GetAuthInfo(); #endregion #region Events /// /// The current program scene has changed. /// event EventHandler CurrentProgramSceneChanged; /// /// The list of scenes has changed. /// TODO: Make OBS fire this event when scenes are reordered. /// event EventHandler SceneListChanged; /// /// Triggered when the scene item list of the specified scene is reordered /// event EventHandler SceneItemListReindexed; /// /// Triggered when a new item is added to the item list of the specified scene /// event EventHandler SceneItemCreated; /// /// Triggered when an item is removed from the item list of the specified scene /// event EventHandler SceneItemRemoved; /// /// Triggered when the visibility of a scene item changes /// event EventHandler SceneItemEnableStateChanged; /// /// Triggered when the lock status of a scene item changes /// event EventHandler SceneItemLockStateChanged; /// /// Triggered when switching to another scene collection /// event EventHandler CurrentSceneCollectionChanged; /// /// Triggered when a scene collection is created, deleted or renamed /// event EventHandler SceneCollectionListChanged; /// /// Triggered when switching to another transition /// event EventHandler CurrentSceneTransitionChanged; /// /// Triggered when the current transition duration is changed /// event EventHandler CurrentSceneTransitionDurationChanged; /// /// Triggered when a transition between two scenes starts. Followed by /// event EventHandler SceneTransitionStarted; /// /// Triggered when a transition (other than "cut") has ended. Please note that the from-scene field is not available in TransitionEnd /// event EventHandler SceneTransitionEnded; /// /// Triggered when a stinger transition has finished playing its video /// event EventHandler SceneTransitionVideoEnded; /// /// Triggered when switching to another profile /// event EventHandler CurrentProfileChanged; /// /// Triggered when a profile is created, imported, removed or renamed /// event EventHandler ProfileListChanged; /// /// Triggered when the streaming output state changes /// event EventHandler StreamStateChanged; /// /// Triggered when the recording output state changes /// event EventHandler RecordStateChanged; /// /// Triggered when state of the replay buffer changes /// event EventHandler ReplayBufferStateChanged; /// /// Triggered when the preview scene selection changes (Studio Mode only) /// event EventHandler CurrentPreviewSceneChanged; /// /// Triggered when Studio Mode is turned on or off /// event EventHandler StudioModeStateChanged; /// /// Triggered when OBS exits /// event EventHandler ExitStarted; /// /// Triggered when connected successfully to an obs-websocket server /// event EventHandler Connected; /// /// Triggered when disconnected from an obs-websocket server /// event EventHandler Disconnected; /// /// A scene item is selected in the UI /// event EventHandler SceneItemSelected; /// /// A scene item transform has changed /// event EventHandler SceneItemTransformChanged; /// /// The audio sync offset of an input has changed /// event EventHandler InputAudioSyncOffsetChanged; /// /// A filter was added to a source /// event EventHandler SourceFilterCreated; /// /// A filter was removed from a source /// event EventHandler SourceFilterRemoved; /// /// Filters in a source have been reordered /// event EventHandler SourceFilterListReindexed; /// /// Triggered when the visibility of a filter has changed /// event EventHandler SourceFilterEnableStateChanged; /// /// A source has been muted or unmuted /// event EventHandler InputMuteStateChanged; /// /// The volume of a source has changed /// event EventHandler InputVolumeChanged; /// /// A custom broadcast message was received /// event EventHandler VendorEvent; /// /// These events are emitted by the OBS sources themselves. For example when the media file ends. The behavior depends on the type of media source being used. /// event EventHandler MediaInputPlaybackEnded; /// /// These events are emitted by the OBS sources themselves. For example when the media file starts playing. The behavior depends on the type of media source being used. /// event EventHandler MediaInputPlaybackStarted; /// /// This event is only emitted when something actively controls the media/VLC source. In other words, the source will never emit this on its own naturally. /// event EventHandler MediaInputActionTriggered; /// /// The virtual cam state has changed. /// event EventHandler VirtualcamStateChanged; /// /// The current scene collection has begun changing. /// event EventHandler CurrentSceneCollectionChanging; /// /// The current profile has begun changing. /// event EventHandler CurrentProfileChanging; /// /// The name of a source filter has changed. /// event EventHandler SourceFilterNameChanged; /// /// An input has been created. /// event EventHandler InputCreated; /// /// An input has been removed. /// event EventHandler InputRemoved; /// /// The name of an input has changed. /// event EventHandler InputNameChanged; /// /// An input's active state has changed. /// When an input is active, it means it's being shown by the program feed. /// event EventHandler InputActiveStateChanged; /// /// An input's show state has changed. /// When an input is showing, it means it's being shown by the preview or a dialog. /// event EventHandler InputShowStateChanged; /// /// The audio balance value of an input has changed. /// event EventHandler InputAudioBalanceChanged; /// /// The audio tracks of an input have changed. /// event EventHandler InputAudioTracksChanged; /// /// The monitor type of an input has changed. /// Available types are: /// - `OBS_MONITORING_TYPE_NONE` /// - `OBS_MONITORING_TYPE_MONITOR_ONLY` /// - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` /// event EventHandler InputAudioMonitorTypeChanged; /// /// A high-volume event providing volume levels of all active inputs every 50 milliseconds. /// event EventHandler InputVolumeMeters; /// /// The replay buffer has been saved. /// event EventHandler ReplayBufferSaved; /// /// A new scene has been created. /// event EventHandler SceneCreated; /// /// A scene has been removed. /// event EventHandler SceneRemoved; /// /// The name of a scene has changed. /// event EventHandler SceneNameChanged; #endregion } } ================================================ FILE: obs-websocket-dotnet/LICENSE.md ================================================ The MIT License (MIT) Copyright (c) 2021 BarRaider Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: obs-websocket-dotnet/OBSWebsocket.cs ================================================ using System; using System.Collections.Concurrent; using System.Net.WebSockets; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OBSWebsocketDotNet.Communication; using Websocket.Client; namespace OBSWebsocketDotNet { public partial class OBSWebsocket : IOBSWebsocket { #region Private Members private const string WEBSOCKET_URL_PREFIX = "ws://"; private const int SUPPORTED_RPC_VERSION = 1; private TimeSpan wsTimeout = TimeSpan.FromSeconds(10); private string connectionPassword = null; private WebsocketClient wsConnection; private delegate void RequestCallback(OBSWebsocket sender, JObject body); private readonly ConcurrentDictionary> responseHandlers; // Random should never be created inside a function private static readonly Random random = new Random(); #endregion /// /// WebSocket request timeout, represented as a TimeSpan object /// public TimeSpan WSTimeout { get { return wsConnection?.ReconnectTimeout ?? wsTimeout; } set { wsTimeout = value; if (wsConnection != null) { wsConnection.ReconnectTimeout = wsTimeout; } } } /// /// Current connection state /// public bool IsConnected { get { return (wsConnection != null && wsConnection.IsRunning); } } /// /// Gets or sets the logger for this instance /// public ILogger Logger { get; set; } = NullLogger.Instance; /// /// Constructor /// public OBSWebsocket() { responseHandlers = new ConcurrentDictionary>(); } /// /// Connect this instance to the specified URL, and authenticate (if needed) with the specified password. /// NOTE: Please subscribe to the Connected/Disconnected events (or atleast check the IsConnected property) to determine when the connection is actually fully established /// /// Server URL in standard URL format. /// Server password [Obsolete("Please use ConnectAsync, this function will be removed in the next version")] public void Connect(string url, string password) { ConnectAsync(url, password); } /// /// Connect this instance to the specified URL, and authenticate (if needed) with the specified password. /// NOTE: Please subscribe to the Connected/Disconnected events (or atleast check the IsConnected property) to determine when the connection is actually fully established /// /// Server URL in standard URL format. /// Server password public void ConnectAsync(string url, string password) { if (!url.ToLower().StartsWith(WEBSOCKET_URL_PREFIX)) { throw new ArgumentException($"Invalid url, must start with '{WEBSOCKET_URL_PREFIX}'"); } if (wsConnection != null && wsConnection.IsRunning) { Disconnect(); } wsConnection = new WebsocketClient(new Uri(url)); wsConnection.IsReconnectionEnabled = false; wsConnection.ReconnectTimeout = null; wsConnection.ErrorReconnectTimeout = null; wsConnection.MessageReceived.Subscribe(m => Task.Run(() => WebsocketMessageHandler(this, m))); wsConnection.DisconnectionHappened.Subscribe(d => Task.Run(() => OnWebsocketDisconnect(this, d))); connectionPassword = password; wsConnection.StartOrFail(); } /// /// Disconnect this instance from the server /// public void Disconnect() { connectionPassword = null; if (wsConnection != null) { // Attempt to both close and dispose the existing connection try { wsConnection.Stop(WebSocketCloseStatus.NormalClosure, "User requested disconnect"); ((IDisposable)wsConnection).Dispose(); } catch { } wsConnection = null; } var unusedHandlers = responseHandlers.ToArray(); responseHandlers.Clear(); foreach (var cb in unusedHandlers) { var tcs = cb.Value; tcs.TrySetCanceled(); } } // This callback handles a websocket disconnection private void OnWebsocketDisconnect(object sender, DisconnectionInfo d) { if (d == null || d.CloseStatus == null) { Disconnected?.Invoke(sender, new ObsDisconnectionInfo(ObsCloseCodes.UnknownReason, null, d)); } else { Disconnected?.Invoke(sender, new ObsDisconnectionInfo((ObsCloseCodes)d.CloseStatus, d.CloseStatusDescription, d)); } } // This callback handles incoming JSON messages and determines if it's // a request response or an event ("Update" in obs-websocket terminology) private void WebsocketMessageHandler(object sender, ResponseMessage e) { if (e.MessageType != WebSocketMessageType.Text) { return; } ServerMessage msg = JsonConvert.DeserializeObject(e.Text); JObject body = msg.Data; switch (msg.OperationCode) { case MessageTypes.Hello: // First message received after connection, this may ask us for authentication HandleHello(body); break; case MessageTypes.Identified: Task.Run(() => Connected?.Invoke(this, EventArgs.Empty)); break; case MessageTypes.RequestResponse: case MessageTypes.RequestBatchResponse: // Handle response to previous request if (body.ContainsKey("requestId")) { // Handle a request : // Find the response handler based on // its associated message ID string msgID = (string)body["requestId"]; if (responseHandlers.TryRemove(msgID, out TaskCompletionSource handler)) { // Set the response body as Result and notify the request sender handler.SetResult(body); } } break; case MessageTypes.Event: // Handle events string eventType = body["eventType"].ToString(); Task.Run(() => { ProcessEventType(eventType, body); }); break; default: // Unsupported message type Logger?.LogWarning($"Unsupported message type: {msg.OperationCode}"); UnsupportedEvent?.Invoke(this, new Types.Events.UnsupportedEventArgs(msg.OperationCode.ToString(), body)); break; } } /// /// Sends a message to the websocket API with the specified request type and optional parameters /// /// obs-websocket request type, must be one specified in the protocol specification /// additional JSON fields if required by the request type /// The server's JSON response as a JObject public JObject SendRequest(string requestType, JObject additionalFields = null) { return SendRequest(MessageTypes.Request, requestType, additionalFields, true); } /// /// Internal version which allows to set the opcode /// Sends a message to the websocket API with the specified request type and optional parameters /// /// Type/OpCode for this messaage /// obs-websocket request type, must be one specified in the protocol specification /// additional JSON fields if required by the request type /// Should wait for reply vs "fire and forget" /// The server's JSON response as a JObject internal JObject SendRequest(MessageTypes operationCode, string requestType, JObject additionalFields = null, bool waitForReply = true) { if (wsConnection == null) { throw new NullReferenceException("Websocket is not initialized"); } // Prepare the asynchronous response handler var tcs = new TaskCompletionSource(); JObject message = null; do { // Generate a random message id message = MessageFactory.BuildMessage(operationCode, requestType, additionalFields, out string messageId); if (!waitForReply || responseHandlers.TryAdd(messageId, tcs)) { break; } // Message id already exists, retry with a new one. } while (true); // Send the message wsConnection.Send(message.ToString()); if (!waitForReply) { return null; } // Wait for a response (received and notified by the websocket response handler) tcs.Task.Wait(wsTimeout.Milliseconds); if (tcs.Task.IsCanceled) throw new ErrorResponseException("Request canceled", 0); // Throw an exception if the server returned an error. // An error occurs if authentication fails or one if the request body is invalid. var result = tcs.Task.Result; if (!(bool)result["requestStatus"]["result"]) { var status = (JObject)result["requestStatus"]; throw new ErrorResponseException($"ErrorCode: {status["code"]}{(status.ContainsKey("comment") ? $", Comment: {status["comment"]}" : "")}", (int)status["code"]); } if (result.ContainsKey("responseData")) // ResponseData is optional return result["responseData"].ToObject(); return new JObject(); } /// /// Request authentication data. You don't have to call this manually. /// /// Authentication data in an object public OBSAuthInfo GetAuthInfo() { JObject response = SendRequest("GetAuthRequired"); return new OBSAuthInfo(response); } /// /// Authenticates to the Websocket server using the challenge and salt given in the passed object /// /// User password /// Authentication data /// true if authentication succeeds, false otherwise protected void SendIdentify(string password, OBSAuthInfo authInfo = null) { var requestFields = new JObject { { "rpcVersion", SUPPORTED_RPC_VERSION } }; if (authInfo != null) { // Authorization required string secret = HashEncode(password + authInfo.PasswordSalt); string authResponse = HashEncode(secret + authInfo.Challenge); requestFields.Add("authentication", authResponse); } SendRequest(MessageTypes.Identify, null, requestFields, false); } /// /// Encode a Base64-encoded SHA-256 hash /// /// source string /// protected string HashEncode(string input) { using var sha256 = new SHA256Managed(); byte[] textBytes = Encoding.ASCII.GetBytes(input); byte[] hash = sha256.ComputeHash(textBytes); return System.Convert.ToBase64String(hash); } /// /// Generate a message ID /// /// (optional) message ID length /// A random string of alphanumerical characters protected string NewMessageID(int length = 16) { const string pool = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; string result = ""; for (int i = 0; i < length; i++) { int index = random.Next(0, pool.Length - 1); result += pool[index]; } return result; } private void HandleHello(JObject payload) { if (!wsConnection.IsStarted) { return; } OBSAuthInfo authInfo = null; if (payload.ContainsKey("authentication")) { // Authentication required authInfo = new OBSAuthInfo((JObject)payload["authentication"]); } SendIdentify(connectionPassword, authInfo); connectionPassword = null; } } } ================================================ FILE: obs-websocket-dotnet/OBSWebsocket_Requests.cs ================================================ using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OBSWebsocketDotNet.Types; using System; using System.Collections.Generic; using System.Linq; using System.Net.NetworkInformation; namespace OBSWebsocketDotNet { /// /// Instance of a connection with an obs-websocket server /// public partial class OBSWebsocket { #region Private Constants private const string REQUEST_FIELD_VOLUME_DB = "inputVolumeDb"; private const string REQUEST_FIELD_VOLUME_MUL = "inputVolumeMul"; private const string RESPONSE_FIELD_IMAGE_DATA = "imageData"; #endregion /// /// Get basic OBS video information /// public ObsVideoSettings GetVideoSettings() { JObject response = SendRequest(nameof(GetVideoSettings)); return JsonConvert.DeserializeObject(response.ToString()); } /// /// Saves a screenshot of a source to the filesystem. /// The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. /// If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. /// **Compatible with inputs and scenes.** /// /// Name of the source to take a screenshot of /// Image compression format to use. Use `GetVersion` to get compatible image formats /// Path to save the screenshot file to. Eg. `C:\\Users\\user\\Desktop\\screenshot.png` /// Width to scale the screenshot to /// Height to scale the screenshot to /// Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use \"default\" (whatever that means, idk) /// Base64-encoded screenshot string public string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1) { var request = new JObject { { nameof(sourceName), sourceName }, { nameof(imageFormat), imageFormat }, { nameof(imageFilePath), imageFilePath } }; if (imageWidth > -1) { request.Add(nameof(imageWidth), imageWidth); } if (imageHeight > -1) { request.Add(nameof(imageHeight), imageHeight); } if (imageCompressionQuality > -1) { request.Add(nameof(imageCompressionQuality), imageCompressionQuality); } var response = SendRequest(nameof(SaveSourceScreenshot), request); return (string)response["imageData"]; } /// /// Saves a screenshot of a source to the filesystem. /// The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. /// If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. /// **Compatible with inputs and scenes.** /// /// Name of the source to take a screenshot of /// Image compression format to use. Use `GetVersion` to get compatible image formats /// Path to save the screenshot file to. Eg. `C:\\Users\\user\\Desktop\\screenshot.png` /// Base64-encoded screenshot string public string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath) { return SaveSourceScreenshot(sourceName, imageFormat, imageFilePath, -1, -1); } /// /// Executes hotkey routine, identified by hotkey unique name /// /// Unique name of the hotkey, as defined when registering the hotkey (e.g. "ReplayBuffer.Save") public void TriggerHotkeyByName(string hotkeyName) { var request = new JObject { { nameof(hotkeyName), hotkeyName } }; SendRequest(nameof(TriggerHotkeyByName), request); } /// /// Triggers a hotkey using a sequence of keys. /// /// Main key identifier (e.g. OBS_KEY_A for key "A"). Available identifiers are here: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-hotkeys.h /// Optional key modifiers object. You can combine multiple key operators. e.g. KeyModifier.Shift | KeyModifier.Control public void TriggerHotkeyByKeySequence(OBSHotkey keyId, KeyModifier keyModifier = KeyModifier.None) { var request = new JObject { { nameof(keyId), keyId.ToString() }, { "keyModifiers", new JObject{ { "shift", (keyModifier & KeyModifier.Shift) == KeyModifier.Shift }, { "alt", (keyModifier & KeyModifier.Alt) == KeyModifier.Alt }, { "control", (keyModifier & KeyModifier.Control) == KeyModifier.Control }, { "command", (keyModifier & KeyModifier.Command) == KeyModifier.Command } } } }; SendRequest(nameof(TriggerHotkeyByKeySequence), request); } /// /// Get the name of the currently active scene. /// /// Name of the current scene public string GetCurrentProgramScene() { JObject response = SendRequest(nameof(GetCurrentProgramScene)); return (string)response["currentProgramSceneName"]; } /// /// Set the current scene to the specified one /// /// The desired scene name public void SetCurrentProgramScene(string sceneName) { var request = new JObject { { nameof(sceneName), sceneName } }; SendRequest(nameof(SetCurrentProgramScene), request); } /// /// Get OBS stats (almost the same info as provided in OBS' stats window) /// public ObsStats GetStats() { JObject response = SendRequest(nameof(GetStats)); return JsonConvert.DeserializeObject(response.ToString()); } /// /// List every available scene /// /// A of objects describing each scene public List ListScenes() { var response = GetSceneList(); return response.Scenes; } /// /// Get a list of scenes in the currently active profile /// public GetSceneListInfo GetSceneList() { JObject response = SendRequest(nameof(GetSceneList)); return JsonConvert.DeserializeObject(response.ToString()); } /// /// Get the specified scene's transition override info /// /// Name of the scene to return the override info /// TransitionOverrideInfo public TransitionOverrideInfo GetSceneSceneTransitionOverride(string sceneName) { var request = new JObject { { nameof(sceneName), sceneName } }; JObject response = SendRequest(nameof(GetSceneSceneTransitionOverride), request); return response.ToObject(); } /// /// Set specific transition override for a scene /// /// Name of the scene to set the transition override /// Name of the transition to use /// Duration in milliseconds of the transition if transition is not fixed. Defaults to the current duration specified in the UI if there is no current override and this value is not given public void SetSceneSceneTransitionOverride(string sceneName, string transitionName, int transitionDuration = -1) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(transitionName), transitionName } }; if (transitionDuration >= 0) { request.Add(nameof(transitionDuration), transitionDuration); } SendRequest(nameof(SetSceneSceneTransitionOverride), request); } /// /// If your code needs to perform multiple successive T-Bar moves (e.g. : in an animation, or in response to a user moving a T-Bar control in your User Interface), set release to false and call ReleaseTBar later once the animation/interaction is over. /// /// T-Bar position. This value must be between 0.0 and 1.0. /// Whether or not the T-Bar gets released automatically after setting its new position (like a user releasing their mouse button after moving the T-Bar). Call ReleaseTBar manually if you set release to false. Defaults to true. public void SetTBarPosition(double position, bool release = true) { if (position < 0.0 || position > 1.0) { throw new ArgumentOutOfRangeException(nameof(position)); } var request = new JObject { { nameof(position), position }, { nameof(release), release} }; SendRequest(nameof(SetTBarPosition), request); } /// /// Apply settings to a source filter /// /// Source with filter /// Filter name /// JObject with filter settings /// Apply over existing settings? public void SetSourceFilterSettings(string sourceName, string filterName, JObject filterSettings, bool overlay = false) { var request = new JObject { { nameof(sourceName), sourceName }, { nameof(filterName), filterName }, { nameof(filterSettings), filterSettings }, { nameof(overlay), overlay } }; SendRequest(nameof(SetSourceFilterSettings), request); } /// /// Apply settings to a source filter /// /// Source with filter /// Filter name /// Filter settings /// Apply over existing settings? public void SetSourceFilterSettings(string sourceName, string filterName, FilterSettings filterSettings, bool overlay = false) { SetSourceFilterSettings(sourceName, filterName, JObject.FromObject(filterSettings), overlay); } /// /// Modify the Source Filter's visibility /// /// Source name /// Source filter name /// New filter state public void SetSourceFilterEnabled(string sourceName, string filterName, bool filterEnabled) { var request = new JObject { { nameof(sourceName), sourceName }, { nameof(filterName), filterName }, { nameof(filterEnabled), filterEnabled } }; SendRequest(nameof(SetSourceFilterEnabled), request); } /// /// Return a list of all filters on a source /// /// Source name public List GetSourceFilterList(string sourceName) { var request = new JObject { { nameof(sourceName), sourceName } }; JObject response = SendRequest(nameof(GetSourceFilterList), request); if (!response.HasValues) { return new List(); } return JsonConvert.DeserializeObject>(response["filters"].ToString()); } /// /// Return a list of settings for a specific filter /// /// Source name /// Filter name public FilterSettings GetSourceFilter(string sourceName, string filterName) { var request = new JObject { { nameof(sourceName), sourceName }, { nameof(filterName), filterName } }; JObject response = SendRequest(nameof(GetSourceFilter), request); return JsonConvert.DeserializeObject(response.ToString()); } /// /// Remove the filter from a source /// /// Name of the source the filter is on /// Name of the filter to remove public bool RemoveSourceFilter(string sourceName, string filterName) { var request = new JObject { { nameof(sourceName), sourceName }, { nameof(filterName), filterName } }; try { SendRequest(nameof(RemoveSourceFilter), request); return true; } catch (Exception e) { //TODO exception handling Logger?.LogError(e, "Error removing filter"); } return false; } /// /// Add a filter to a source /// /// Name of the source for the filter /// Name of the filter /// Type of filter /// JObject holding filter settings object public void CreateSourceFilter(string sourceName, string filterName, string filterKind, JObject filterSettings) { var request = new JObject { { nameof(sourceName), sourceName }, { nameof(filterName), filterName }, { nameof(filterKind), filterKind }, { nameof(filterSettings), filterSettings } }; SendRequest(nameof(CreateSourceFilter), request); } /// /// Add a filter to a source /// /// Name of the source for the filter /// Name of the filter /// Type of filter /// Filter settings object public void CreateSourceFilter(string sourceName, string filterName, string filterKind, FilterSettings filterSettings) { CreateSourceFilter(sourceName, filterName, filterKind, JObject.FromObject(filterSettings)); } /// /// Toggles the status of the stream output. /// /// New state of the stream output public bool ToggleStream() { var response = SendRequest(nameof(ToggleStream)); return (bool)response["outputActive"]; } /// /// Toggles the status of the record output. /// public void ToggleRecord() { SendRequest(nameof(ToggleRecord)); } /// /// Gets the status of the stream output /// /// An object describing the current outputs states public OutputStatus GetStreamStatus() { var response = SendRequest(nameof(GetStreamStatus)); var outputStatus = new OutputStatus(response); return outputStatus; } /// /// Get the current transition name and duration /// /// An object with the current transition name and duration public TransitionSettings GetCurrentSceneTransition() { var response = SendRequest(nameof(GetCurrentSceneTransition)); return new TransitionSettings(response); } /// /// Set the current transition to the specified one /// /// Desired transition name public void SetCurrentSceneTransition(string transitionName) { var request = new JObject { { nameof(transitionName), transitionName } }; SendRequest(nameof(SetCurrentSceneTransition), request); } /// /// Change the transition's duration /// /// Desired transition duration (in milliseconds) public void SetCurrentSceneTransitionDuration(int transitionDuration) { var request = new JObject { { nameof(transitionDuration), transitionDuration } }; SendRequest(nameof(SetCurrentSceneTransitionDuration), request); } /// /// Change the current settings of a transition /// /// Transition settings (they can be partial) /// Whether to overlay over the current settins or replace them /// Updated transition settings public void SetCurrentSceneTransitionSettings(JObject transitionSettings, bool overlay) { var requestFields = new JObject { { nameof(transitionSettings), JToken.FromObject(transitionSettings)}, { nameof(overlay), overlay } }; var response = SendRequest(nameof(SetCurrentSceneTransitionSettings), requestFields); } /// /// Change the volume of the specified source /// /// Name of the source which volume will be changed /// Desired volume. Must be between `0.0` and `1.0` for amplitude/mul (useDecibel is false), and under 0.0 for dB (useDecibel is true). Note: OBS will interpret dB values under -100.0 as Inf. /// Interperet `volume` data as decibels instead of amplitude/mul. public void SetInputVolume(string inputName, float inputVolume, bool inputVolumeDb = false) { var requestFields = new JObject { { nameof(inputName), inputName } }; if (inputVolumeDb) { requestFields.Add(REQUEST_FIELD_VOLUME_DB, inputVolume); } else { requestFields.Add(REQUEST_FIELD_VOLUME_MUL, inputVolume); } SendRequest(nameof(SetInputVolume), requestFields); } /// /// Get the volume of the specified source /// Volume is between `0.0` and `1.0` if using amplitude/mul (useDecibel is false), under `0.0` if using dB (useDecibel is true). /// /// Source name /// An Object containing the volume and mute state of the specified source. public VolumeInfo GetInputVolume(string inputName) { var request = new JObject { { nameof(inputName), inputName } }; var response = SendRequest(nameof(GetInputVolume), request); return new VolumeInfo(response); } /// /// Gets the audio mute state of an input. /// /// Name of input to get the mute state of /// Whether the input is muted public bool GetInputMute(string inputName) { var requestFields = new JObject { { nameof(inputName), inputName } }; var response = SendRequest(nameof(GetInputMute), requestFields); return (bool)response["inputMuted"]; } /// /// Set the mute state of the specified source /// /// Name of the source which mute state will be changed /// Desired mute state public void SetInputMute(string inputName, bool inputMuted) { var requestFields = new JObject { { nameof(inputName), inputName }, { nameof(inputMuted), inputMuted } }; SendRequest(nameof(SetInputMute), requestFields); } /// /// Toggle the mute state of the specified source /// /// Name of the source which mute state will be toggled public void ToggleInputMute(string inputName) { var requestFields = new JObject { { nameof(inputName), inputName } }; SendRequest(nameof(ToggleInputMute), requestFields); } /// /// Sets the transform and crop info of a scene item /// /// Name of the scene that has the SceneItem /// Id of the Scene Item /// JObject holding transform settings public void SetSceneItemTransform(string sceneName, int sceneItemId, JObject sceneItemTransform) { var requestFields = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId }, { nameof(sceneItemTransform), sceneItemTransform } }; SendRequest(nameof(SetSceneItemTransform), requestFields); } /// /// Sets the transform and crop info of a scene item /// /// Name of the scene that has the SceneItem /// Id of the Scene Item /// Transform settings public void SetSceneItemTransform(string sceneName, int sceneItemId, SceneItemTransformInfo sceneItemTransform) { SetSceneItemTransform(sceneName, sceneItemId, JObject.FromObject(sceneItemTransform)); } /// /// Set the current scene collection to the specified one /// /// Desired scene collection name public void SetCurrentSceneCollection(string sceneCollectionName) { var requestFields = new JObject { { nameof(sceneCollectionName), sceneCollectionName } }; SendRequest(nameof(SetCurrentSceneCollection), requestFields); } /// /// Get the name of the current scene collection /// /// Name of the current scene collection public string GetCurrentSceneCollection() { var response = SendRequest(nameof(GetSceneCollectionList)); var currentCollectionName = response["currentSceneCollectionName"]; return (string)currentCollectionName; } /// /// List all scene collections /// /// A of the names of all scene collections public List GetSceneCollectionList() { var response = SendRequest(nameof(GetSceneCollectionList)); return JsonConvert.DeserializeObject>(response["sceneCollections"].ToString()); } /// /// Set the current profile to the specified one /// /// Name of the desired profile public void SetCurrentProfile(string profileName) { var requestFields = new JObject { { nameof(profileName), profileName } }; SendRequest(nameof(SetCurrentProfile), requestFields); } /// /// List all profiles /// /// A of the names of all profiles public GetProfileListInfo GetProfileList() { var response = SendRequest(nameof(GetProfileList)); return JsonConvert.DeserializeObject(response.ToString()); } /// /// Start streaming. Will trigger an error if streaming is already active /// public void StartStream() { SendRequest(nameof(StartStream)); } /// /// Stop streaming. Will trigger an error if streaming is not active. /// public void StopStream() { SendRequest(nameof(StopStream)); } /// /// Start recording. Will trigger an error if recording is already active. /// public void StartRecord() { SendRequest(nameof(StartRecord)); } /// /// Stop recording. Will trigger an error if recording is not active. /// File name for the saved recording /// public string StopRecord() { var response = SendRequest(nameof(StopRecord)); return (string)response["outputPath"]; } /// /// Pause the current recording. Returns an error if recording is not active or already paused. /// public void PauseRecord() { SendRequest(nameof(PauseRecord)); } /// /// Resume/unpause the current recording (if paused). Returns an error if recording is not active or not paused. /// public void ResumeRecord() { SendRequest(nameof(ResumeRecord)); } /// /// Get the path of the current recording folder /// /// Current recording folder path public string GetRecordDirectory() { var response = SendRequest(nameof(GetRecordDirectory)); return (string)response["recordDirectory"]; } /// /// Get current recording status. /// /// public RecordingStatus GetRecordStatus() { var response = SendRequest(nameof(GetRecordStatus)); return JsonConvert.DeserializeObject(response.ToString()); } /// /// Get the status of the OBS replay buffer. /// /// Current recording status. true when active public bool GetReplayBufferStatus() { var response = SendRequest(nameof(GetReplayBufferStatus)); return (bool)response["outputActive"]; } /// /// Get duration of the currently selected transition (if supported) /// /// Current transition duration (in milliseconds) public GetTransitionListInfo GetSceneTransitionList() { var response = SendRequest(nameof(GetSceneTransitionList)); return JsonConvert.DeserializeObject(response.ToString()); } /// /// Get status of Studio Mode /// /// Studio Mode status (on/off) public bool GetStudioModeEnabled() { var response = SendRequest(nameof(GetStudioModeEnabled)); return (bool)response["studioModeEnabled"]; } /// /// Enables or disables studio mode /// /// public void SetStudioModeEnabled(bool studioModeEnabled) { var requestFields = new JObject { { nameof(studioModeEnabled), studioModeEnabled } }; SendRequest(nameof(SetStudioModeEnabled), requestFields); } /// /// Get the name of the currently selected preview scene. /// Note: Triggers an error if Studio Mode is disabled /// /// Preview scene name public string GetCurrentPreviewScene() { var response = SendRequest(nameof(GetCurrentPreviewScene)); return (string)response["currentPreviewSceneName"]; } /// /// Change the currently active preview/studio scene to the one specified. /// Triggers an error if Studio Mode is disabled /// /// Preview scene name public void SetCurrentPreviewScene(string sceneName) { var requestFields = new JObject { { nameof(sceneName), sceneName } }; SendRequest(nameof(SetCurrentPreviewScene), requestFields); } /// /// Change the currently active preview/studio scene to the one specified. /// Triggers an error if Studio Mode is disabled. /// /// Preview scene object public void SetCurrentPreviewScene(ObsScene previewScene) { SetCurrentPreviewScene(previewScene.Name); } /// /// Triggers the current scene transition. Same functionality as the `Transition` button in Studio Mode /// public void TriggerStudioModeTransition() { SendRequest(nameof(TriggerStudioModeTransition)); } /// /// Toggles the state of the replay buffer output. /// public void ToggleReplayBuffer() { SendRequest(nameof(ToggleReplayBuffer)); } /// /// Start recording into the Replay Buffer. Triggers an error /// if the Replay Buffer is already active, or if the "Save Replay Buffer" /// hotkey is not set in OBS' settings /// public void StartReplayBuffer() { SendRequest(nameof(StartReplayBuffer)); } /// /// Stop recording into the Replay Buffer. Triggers an error if the /// Replay Buffer is not active. /// public void StopReplayBuffer() { SendRequest(nameof(StopReplayBuffer)); } /// /// Save and flush the contents of the Replay Buffer to disk. Basically /// the same as triggering the "Save Replay Buffer" hotkey in OBS. /// Triggers an error if Replay Buffer is not active. /// public void SaveReplayBuffer() { SendRequest(nameof(SaveReplayBuffer)); } /// /// Set the audio sync offset of the specified source /// /// Source name /// Audio offset (in nanoseconds) for the specified source public void SetInputAudioSyncOffset(string inputName, int inputAudioSyncOffset) { var requestFields = new JObject { { nameof(inputName), inputName }, { nameof(inputAudioSyncOffset), inputAudioSyncOffset } }; SendRequest(nameof(SetInputAudioSyncOffset), requestFields); } /// /// Get the audio sync offset of the specified source /// /// Source name /// Audio offset (in nanoseconds) of the specified source public int GetInputAudioSyncOffset(string inputName) { var requestFields = new JObject { { nameof(inputName), inputName } }; var response = SendRequest(nameof(GetInputAudioSyncOffset), requestFields); return (int)response["inputAudioSyncOffset"]; } /// /// Removes a scene item from a scene. /// Scenes only. /// /// Scene item id /// Scene name from which to delete item public void RemoveSceneItem(string sceneName, int sceneItemId) { var requestFields = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId } }; SendRequest(nameof(RemoveSceneItem), requestFields); } /// /// Sends CEA-608 caption text over the stream output. As of OBS Studio 23.1, captions are not yet available on Linux. /// /// Captions text public void SendStreamCaption(string captionText) { var requestFields = new JObject { { nameof(captionText), captionText } }; SendRequest(nameof(SendStreamCaption), requestFields); } /// /// Duplicates a scene item /// /// Name of the scene that has the SceneItem /// Id of the Scene Item /// Name of scene to add the new duplicated Scene Item. If not specified will assume sceneName public void DuplicateSceneItem(string sceneName, int sceneItemId, string destinationSceneName = null) { var requestFields = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId } }; if (!String.IsNullOrEmpty(destinationSceneName)) { requestFields.Add(nameof(destinationSceneName), destinationSceneName); } SendRequest(nameof(DuplicateSceneItem), requestFields); } /// /// Gets the names of all special inputs. /// /// Dictionary of special inputs. public Dictionary GetSpecialInputs() { var response = SendRequest(nameof(GetSpecialInputs)); var sources = new Dictionary(); foreach (KeyValuePair kvp in response) { string key = kvp.Key; string value = (string)kvp.Value; if (key != "requestType") { sources.Add(key, value); } } return sources; } /// /// Sets the current stream service settings (stream destination). /// Note: Simple RTMP settings can be set with type `rtmp_custom` and the settings fields `server` and `key`. /// /// Stream Service Type Name and Settings objects public void SetStreamServiceSettings(StreamingService service) { var requestFields = new JObject { { "streamServiceType", service.Type }, { "streamServiceSettings", JToken.FromObject(service.Settings) } }; SendRequest(nameof(SetStreamServiceSettings), requestFields); } /// /// Gets the current stream service settings (stream destination). /// /// Stream service type and settings objects public StreamingService GetStreamServiceSettings() { var response = SendRequest(nameof(GetStreamServiceSettings)); return JsonConvert.DeserializeObject(response.ToString()); } /// /// Gets the audio monitor type of an input. /// The available audio monitor types are: /// - `OBS_MONITORING_TYPE_NONE` /// - `OBS_MONITORING_TYPE_MONITOR_ONLY` /// - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` /// /// Source name /// The monitor type in use public string GetInputAudioMonitorType(string inputName) { var request = new JObject { { nameof(inputName), inputName } }; var response = SendRequest(nameof(GetInputAudioMonitorType), request); return (string)response["monitorType"]; } /// /// Sets the audio monitor type of an input. /// /// Name of the input to set the audio monitor type of /// Audio monitor type. See `GetInputAudioMonitorType for possible types. public void SetInputAudioMonitorType(string inputName, string monitorType) { var request = new JObject { { nameof(inputName), inputName }, { nameof(monitorType), monitorType } }; SendRequest(nameof(SetInputAudioMonitorType), request); } /// /// Broadcasts a `CustomEvent` to all WebSocket clients. Receivers are clients which are identified and subscribed. /// /// Data payload to emit to all receivers public void BroadcastCustomEvent(JObject eventData) { var request = new JObject { { nameof(eventData), eventData } }; SendRequest(nameof(BroadcastCustomEvent), request); } /// /// Sets the cursor position of a media input. /// This request does not perform bounds checking of the cursor position. /// /// Name of the media input /// New cursor position to set (milliseconds). public void SetMediaInputCursor(string inputName, int mediaCursor) { var request = new JObject { { nameof(inputName), inputName }, { nameof(mediaCursor), mediaCursor } }; SendRequest(nameof(SetMediaInputCursor), request); } /// /// Offsets the current cursor position of a media input by the specified value. /// This request does not perform bounds checking of the cursor position. /// /// Name of the media input /// Value to offset the current cursor position by (milliseconds +/-) public void OffsetMediaInputCursor(string inputName, int mediaCursorOffset) { var request = new JObject { { nameof(inputName), inputName }, { nameof(mediaCursorOffset), mediaCursorOffset } }; SendRequest(nameof(OffsetMediaInputCursor), request); } /// /// Creates a new input, adding it as a scene item to the specified scene. /// /// Name of the scene to add the input to as a scene item /// Name of the new input to created /// The kind of input to be created /// Jobject holding the settings object to initialize the input with /// Whether to set the created scene item to enabled or disabled /// ID of the SceneItem in the scene. public int CreateInput(string sceneName, string inputName, string inputKind, JObject inputSettings, bool? sceneItemEnabled) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(inputName), inputName }, { nameof(inputKind), inputKind } }; if (inputSettings != null) { request.Add(nameof(inputSettings), inputSettings); } if (sceneItemEnabled.HasValue) { request.Add(nameof(sceneItemEnabled), sceneItemEnabled.Value); } var response = SendRequest(nameof(CreateInput), request); return (int)response["sceneItemId"]; } /// /// Gets the default settings for an input kind. /// /// Input kind to get the default settings for /// Object of default settings for the input kind public JObject GetInputDefaultSettings(string inputKind) { var request = new JObject { { nameof(inputKind), inputKind } }; var response = SendRequest(nameof(GetInputDefaultSettings), request); return (JObject)response["defaultInputSettings"]; } /// /// Gets a list of all scene items in a scene. /// Scenes only /// /// Name of the scene to get the items of /// Array of scene items in the scene public List GetSceneItemList(string sceneName) { JObject request = null; if (!string.IsNullOrEmpty(sceneName)) { request = new JObject { { nameof(sceneName), sceneName } }; } var response = SendRequest(nameof(GetSceneItemList), request); return response["sceneItems"].Select(m => new SceneItemDetails((JObject)m)).ToList(); } /// /// Creates a new scene item using a source. /// Scenes only /// /// Name of the scene to create the new item in /// Name of the source to add to the scene /// Enable state to apply to the scene item on creation /// Numeric ID of the scene item public int CreateSceneItem(string sceneName, string sourceName, bool sceneItemEnabled = true) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sourceName), sourceName }, { nameof(sceneItemEnabled), sceneItemEnabled } }; var response = SendRequest(nameof(CreateSceneItem), request); return (int)response["sceneItemId"]; } /// /// Creates a new scene in OBS. /// /// Name for the new scene public void CreateScene(string sceneName) { var request = new JObject { { nameof(sceneName), sceneName } }; SendRequest(nameof(CreateScene), request); } /// /// Gets the enable state of all audio tracks of an input. /// /// Name of the input /// Object of audio tracks and associated enable states public SourceTracks GetInputAudioTracks(string inputName) { var request = new JObject { { nameof(inputName), inputName } }; var response = SendRequest(nameof(GetInputAudioTracks), request); return new SourceTracks(response); } /// /// Sets the enable state of audio tracks of an input. /// /// Name of the input /// JObject holding track settings to apply public void SetInputAudioTracks(string inputName, JObject inputAudioTracks) { var request = new JObject { { nameof(inputName), inputName }, { nameof(inputAudioTracks), inputAudioTracks } }; SendRequest(nameof(SetInputAudioTracks), request); } /// /// Sets the enable state of audio tracks of an input. /// /// Name of the input /// Track settings to apply public void SetInputAudioTracks(string inputName, SourceTracks inputAudioTracks) { SetInputAudioTracks(inputName, JObject.FromObject(inputAudioTracks)); } /// /// Gets the active and show state of a source. /// **Compatible with inputs and scenes.** /// /// Name of the source to get the active state of /// Whether the source is showing in Program public SourceActiveInfo GetSourceActive(string sourceName) { var request = new JObject { { nameof(sourceName), sourceName } }; var response = SendRequest(nameof(GetSourceActive), request); return new SourceActiveInfo(response); } /// /// Gets the status of the virtualcam output. /// /// An object describing the current virtual camera state public VirtualCamStatus GetVirtualCamStatus() { JObject response = SendRequest(nameof(GetVirtualCamStatus)); var outputStatus = new VirtualCamStatus(response); return outputStatus; } /// /// Starts the virtualcam output. /// public void StartVirtualCam() { SendRequest(nameof(StartVirtualCam)); } /// /// Stops the virtualcam output. /// public void StopVirtualCam() { SendRequest(nameof(StopVirtualCam)); } /// /// Toggles the state of the virtualcam output. /// /// Whether the output is active public VirtualCamStatus ToggleVirtualCam() { JObject response = SendRequest(nameof(ToggleVirtualCam)); var outputStatus = new VirtualCamStatus(response); return outputStatus; } /// /// Gets the value of a \"slot\" from the selected persistent data realm. /// /// The data realm to select. `OBS_WEBSOCKET_DATA_REALM_GLOBAL` or `OBS_WEBSOCKET_DATA_REALM_PROFILE` /// The name of the slot to retrieve data from /// Value associated with the slot. `null` if not set public JObject GetPersistentData(string realm, string slotName) { var request = new JObject { { nameof(realm), realm }, { nameof(slotName), slotName } }; return SendRequest(nameof(GetPersistentData), request); } /// /// Sets the value of a \"slot\" from the selected persistent data realm. /// /// The data realm to select. `OBS_WEBSOCKET_DATA_REALM_GLOBAL` or `OBS_WEBSOCKET_DATA_REALM_PROFILE` /// The name of the slot to retrieve data from /// The value to apply to the slot public void SetPersistentData(string realm, string slotName, JObject slotValue) { var request = new JObject { { nameof(realm), realm }, { nameof(slotName), slotName }, { nameof(slotValue), slotValue } }; SendRequest(nameof(SetPersistentData), request); } /// /// Creates a new scene collection, switching to it in the process.\n\nNote: This will block until the collection has finished changing. /// /// Name for the new scene collection public void CreateSceneCollection(string sceneCollectionName) { var request = new JObject { { nameof(sceneCollectionName), sceneCollectionName } }; SendRequest(nameof(CreateSceneCollection), request); } /// /// Creates a new profile, switching to it in the process /// /// Name for the new profile public void CreateProfile(string profileName) { var request = new JObject { { nameof(profileName), profileName } }; SendRequest(nameof(CreateProfile), request); } /// /// Removes a profile. If the current profile is chosen, it will change to a different profile first. /// /// Name of the profile to remove public void RemoveProfile(string profileName) { var request = new JObject { { nameof(profileName), profileName } }; SendRequest(nameof(RemoveProfile), request); } /// /// Gets a parameter from the current profile's configuration. /// /// Category of the parameter to get /// Name of the parameter to get /// public JObject GetProfileParameter(string parameterCategory, string parameterName) { var request = new JObject { { nameof(parameterCategory), parameterCategory }, { nameof(parameterName), parameterName } }; return SendRequest(nameof(GetProfileParameter), request); } /// /// Sets the value of a parameter in the current profile's configuration. /// /// Category of the parameter to set /// Name of the parameter to set /// Value of the parameter to set. Use `null` to delete public void SetProfileParameter(string parameterCategory, string parameterName, string parameterValue) { var request = new JObject { { nameof(parameterCategory), parameterCategory }, { nameof(parameterName), parameterName }, { nameof(parameterValue), parameterValue } }; SendRequest(nameof(SetProfileParameter), request); } /// /// Sets the current video settings. /// Note: Fields must be specified in pairs. For example, you cannot set only `baseWidth` without needing to specify `baseHeight`. /// /// Object containing video settings public void SetVideoSettings(ObsVideoSettings obsVideoSettings) { SendRequest(nameof(SetVideoSettings), JObject.FromObject(obsVideoSettings)); } /// /// Gets the default settings for a filter kind. /// /// Filter kind to get the default settings for /// Object of default settings for the filter kind public JObject GetSourceFilterDefaultSettings(string filterKind) { var request = new JObject { { nameof(filterKind), filterKind } }; return SendRequest(nameof(GetSourceFilterDefaultSettings), request); } /// /// Sets the name of a source filter (rename). /// /// Name of the source the filter is on /// Current name of the filter /// New name for the filter public void SetSourceFilterName(string sourceName, string filterName, string newFilterName) { var request = new JObject { { nameof(sourceName), sourceName }, { nameof(filterName), filterName }, { nameof(newFilterName), newFilterName } }; SendRequest(nameof(SetSourceFilterName), request); } /// /// Sets the index position of a filter on a source. /// /// Name of the source the filter is on /// Name of the filter /// New index position of the filter public void SetSourceFilterIndex(string sourceName, string filterName, int filterIndex) { var request = new JObject { { nameof(sourceName), sourceName }, { nameof(filterName), filterName }, { nameof(filterIndex), filterIndex } }; SendRequest(nameof(SetSourceFilterIndex), request); } /// /// Gets data about the current plugin and RPC version. /// /// Version info in an object public ObsVersion GetVersion() { JObject response = SendRequest(nameof(GetVersion)); return new ObsVersion(response); } /// /// Call a request registered to a vendor. /// A vendor is a unique name registered by a third-party plugin or script, which allows for custom requests and events to be added to obs-websocket. /// If a plugin or script implements vendor requests or events, documentation is expected to be provided with them. /// /// Name of the vendor to use /// The request type to call /// Object containing appropriate request data /// Object containing appropriate response data. {} if request does not provide any response data public JObject CallVendorRequest(string vendorName, string requestType, JObject requestData = null) { var request = new JObject { { nameof(vendorName), vendorName }, { nameof(requestType), requestType }, { nameof(requestData), requestData } }; return SendRequest(nameof(CallVendorRequest), request); } /// /// Gets an array of all hotkey names in OBS /// /// Array of hotkey names public List GetHotkeyList() { var response = SendRequest(nameof(GetHotkeyList)); return JsonConvert.DeserializeObject>(response["hotkeys"].ToString()); } /// /// Sleeps for a time duration or number of frames. Only available in request batches with types `SERIAL_REALTIME` or `SERIAL_FRAME`. /// /// Number of milliseconds to sleep for (if `SERIAL_REALTIME` mode) /// Number of frames to sleep for (if `SERIAL_FRAME` mode) public void Sleep(int sleepMillis, int sleepFrames) { var request = new JObject { { nameof(sleepMillis), sleepMillis }, { nameof(sleepFrames), sleepFrames } }; SendRequest(nameof(Sleep), request); } /// /// Gets an array of all inputs in OBS. /// /// Restrict the array to only inputs of the specified kind /// List of Inputs in OBS public List GetInputList(string inputKind = null) { var request = new JObject { { nameof(inputKind), inputKind } }; var response = inputKind is null ? SendRequest(nameof(GetInputList)) : SendRequest(nameof(GetInputList), request); var returnList = new List(); foreach (var input in response["inputs"]) { returnList.Add(new InputBasicInfo(input as JObject)); } return returnList; } /// /// Gets an array of all available input kinds in OBS. /// /// True == Return all kinds as unversioned, False == Return with version suffixes (if available) /// Array of input kinds public List GetInputKindList(bool unversioned = false) { var request = new JObject { { nameof(unversioned), unversioned } }; var response = unversioned is false ? SendRequest(nameof(GetInputKindList)) : SendRequest(nameof(GetInputKindList), request); return JsonConvert.DeserializeObject>(response["inputKinds"].ToString()); } /// /// Removes an existing input. /// Note: Will immediately remove all associated scene items. /// /// Name of the input to remove public void RemoveInput(string inputName) { var request = new JObject { { nameof(inputName), inputName } }; SendRequest(nameof(RemoveInput), request); } /// /// Sets the name of an input (rename). /// /// Current input name /// New name for the input public void SetInputName(string inputName, string newInputName) { var request = new JObject { { nameof(inputName), inputName }, { nameof(newInputName), newInputName } }; SendRequest(nameof(SetInputName), request); } /// /// Gets the settings of an input. /// Note: Does not include defaults. To create the entire settings object, overlay `inputSettings` over the `defaultInputSettings` provided by `GetInputDefaultSettings`. /// /// Name of the input to get the settings of /// New populated InputSettings object public InputSettings GetInputSettings(string inputName) { var request = new JObject { { nameof(inputName), inputName } }; var response = SendRequest(nameof(GetInputSettings), request); response.Merge(request); return new InputSettings(response); } /// /// Sets the settings of an input. /// /// Object of settings to apply /// True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. public void SetInputSettings(InputSettings inputSettings, bool overlay = true) { SetInputSettings(inputSettings.InputName, inputSettings.Settings, overlay); } /// /// Sets the settings of an input. /// /// Name of the input to set the settings of /// Object of settings to apply /// True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. public void SetInputSettings(string inputName, JObject inputSettings, bool overlay = true) { var request = new JObject { { nameof(inputName), inputName }, { nameof(inputSettings), inputSettings }, { nameof(overlay), overlay } }; SendRequest(nameof(SetInputSettings), request); } /// /// Gets the audio balance of an input. /// /// Name of the input to get the audio balance of /// Audio balance value from 0.0-1.0 public double GetInputAudioBalance(string inputName) { var request = new JObject { { nameof(inputName), inputName } }; var response = SendRequest(nameof(GetInputAudioBalance), request); return (double)response["inputAudioBalance"]; } /// /// Sets the audio balance of an input. /// /// Name of the input to set the audio balance of /// New audio balance value public void SetInputAudioBalance(string inputName, double inputAudioBalance) { var request = new JObject { { nameof(inputName), inputName }, { nameof(inputAudioBalance), inputAudioBalance } }; SendRequest(nameof(SetInputAudioBalance), request); } /// /// Gets the items of a list property from an input's properties. /// Note: Use this in cases where an input provides a dynamic, selectable list of items. /// For example, display capture, where it provides a list of available displays. /// /// Name of the input /// Name of the list property to get the items of /// Array of items in the list property public List GetInputPropertiesListPropertyItems(string inputName, string propertyName) { var request = new JObject { { nameof(inputName), inputName }, { nameof(propertyName), propertyName } }; var response = SendRequest(nameof(GetInputPropertiesListPropertyItems), request); return response["propertyItems"].Value>(); } /// /// Presses a button in the properties of an input. /// Note: Use this in cases where there is a button in the properties of an input that cannot be accessed in any other way. /// For example, browser sources, where there is a refresh button. /// /// Name of the input /// Name of the button property to press public void PressInputPropertiesButton(string inputName, string propertyName) { var request = new JObject { { nameof(inputName), inputName }, { nameof(propertyName), propertyName } }; SendRequest(nameof(PressInputPropertiesButton), request); } /// /// Gets the status of a media input.\n\nMedia States: /// - `OBS_MEDIA_STATE_NONE` /// - `OBS_MEDIA_STATE_PLAYING` /// - `OBS_MEDIA_STATE_OPENING` /// - `OBS_MEDIA_STATE_BUFFERING` /// - `OBS_MEDIA_STATE_PAUSED` /// - `OBS_MEDIA_STATE_STOPPED` /// - `OBS_MEDIA_STATE_ENDED` /// - `OBS_MEDIA_STATE_ERROR` /// /// Name of the media input /// Object containing string mediaState, int mediaDuration, int mediaCursor properties public MediaInputStatus GetMediaInputStatus(string inputName) { var request = new JObject { { nameof(inputName), inputName } }; return new MediaInputStatus(SendRequest(nameof(GetMediaInputStatus), request)); } /// /// Triggers an action on a media input. /// /// Name of the media input /// Identifier of the `ObsMediaInputAction` enum public void TriggerMediaInputAction(string inputName, string mediaAction) { var request = new JObject { { nameof(inputName), inputName }, { nameof(mediaAction), mediaAction } }; SendRequest(nameof(TriggerMediaInputAction), request); } /// /// Gets the filename of the last replay buffer save file. /// /// File path of last replay public string GetLastReplayBufferReplay() { var response = SendRequest(nameof(GetLastReplayBufferReplay)); return (string)response["savedReplayPath"]; } /// /// Toggles pause on the record output. /// public void ToggleRecordPause() { SendRequest(nameof(ToggleRecordPause)); } /// /// Currently BROKEN in obs-websocket/obs-studio /// Basically GetSceneItemList, but for groups. /// Using groups at all in OBS is discouraged, as they are very broken under the hood. /// Groups only /// /// Name of the group to get the items of /// Array of scene items in the group public List GetGroupSceneItemList(string sceneName) { var request = new JObject { { nameof(sceneName), sceneName } }; var response = SendRequest(nameof(GetGroupSceneItemList), request); return JsonConvert.DeserializeObject>((string)response["sceneItems"]); } /// /// Searches a scene for a source, and returns its id.\n\nScenes and Groups /// /// Name of the scene or group to search in /// Name of the source to find /// Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item /// Numeric ID of the scene item public int GetSceneItemId(string sceneName, string sourceName, int searchOffset) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sourceName), sourceName }, { nameof(searchOffset), searchOffset } }; var response = SendRequest(nameof(GetSceneItemId), request); return (int)response["sceneItemId"]; } /// /// Gets the transform and crop info of a scene item. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Object containing scene item transform info public SceneItemTransformInfo GetSceneItemTransform(string sceneName, int sceneItemId) { var response = GetSceneItemTransformRaw(sceneName, sceneItemId); return JsonConvert.DeserializeObject(response["sceneItemTransform"].ToString()); } /// /// Gets the JObject of transform settings for a scene item. Use this one you don't want it populated with default values. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Object containing scene item transform info public JObject GetSceneItemTransformRaw(string sceneName, int sceneItemId) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId } }; return SendRequest(nameof(GetSceneItemTransform), request); } /// /// Gets the enable state of a scene item. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Whether the scene item is enabled. `true` for enabled, `false` for disabled public bool GetSceneItemEnabled(string sceneName, int sceneItemId) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId } }; var response = SendRequest(nameof(GetSceneItemEnabled), request); return (bool)response["sceneItemEnabled"]; } /// /// Gets the enable state of a scene item. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// New enable state of the scene item public void SetSceneItemEnabled(string sceneName, int sceneItemId, bool sceneItemEnabled) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId }, { nameof(sceneItemEnabled), sceneItemEnabled } }; SendRequest(nameof(SetSceneItemEnabled), request); } /// /// Gets the lock state of a scene item. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Whether the scene item is locked. `true` for locked, `false` for unlocked public bool GetSceneItemLocked(string sceneName, int sceneItemId) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId } }; var response = SendRequest(nameof(GetSceneItemLocked), request); return (bool)response["sceneItemLocked"]; } /// /// Sets the lock state of a scene item. /// Scenes and Group /// /// Name of the scene the item is in /// Numeric ID of the scene item /// New lock state of the scene item public void SetSceneItemLocked(string sceneName, int sceneItemId, bool sceneItemLocked) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId }, { nameof(sceneItemLocked), sceneItemLocked } }; SendRequest(nameof(SetSceneItemLocked), request); } /// /// Gets the index position of a scene item in a scene. /// An index of 0 is at the bottom of the source list in the UI. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Index position of the scene item public int GetSceneItemIndex(string sceneName, int sceneItemId) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId } }; var response = SendRequest(nameof(GetSceneItemIndex), request); return (int)response["sceneItemIndex"]; } /// /// Sets the index position of a scene item in a scene. /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// New index position of the scene item public void SetSceneItemIndex(string sceneName, int sceneItemId, int sceneItemIndex) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId }, { nameof(sceneItemIndex), sceneItemIndex } }; SendRequest(nameof(SetSceneItemIndex), request); } /// /// Gets the blend mode of a scene item. /// Blend modes: /// - `OBS_BLEND_NORMAL` /// - `OBS_BLEND_ADDITIVE` /// - `OBS_BLEND_SUBTRACT` /// - `OBS_BLEND_SCREEN` /// - `OBS_BLEND_MULTIPLY` /// - `OBS_BLEND_LIGHTEN` /// - `OBS_BLEND_DARKEN` /// Scenes and Groups /// /// Name of the scene the item is in /// Numeric ID of the scene item /// Current blend mode public string GetSceneItemBlendMode(string sceneName, int sceneItemId) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId } }; var response = SendRequest(nameof(GetSceneItemBlendMode), request); return (string)response["sceneItemBlendMode"]; } /// /// Sets the blend mode of a scene item. /// Scenes and Groups /// /// /// /// public void SetSceneItemBlendMode(string sceneName, int sceneItemId, string sceneItemBlendMode) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(sceneItemId), sceneItemId }, { nameof(sceneItemBlendMode), sceneItemBlendMode } }; SendRequest(nameof(SetSceneItemBlendMode), request); } /// /// Gets an array of all groups in OBS. /// Groups in OBS are actually scenes, but renamed and modified. In obs-websocket, we treat them as scenes where we can. /// /// Array of group names public List GetGroupList() { var response = SendRequest(nameof(GetGroupList)); return JsonConvert.DeserializeObject>(response["groups"].ToString()); } /// /// Removes a scene from OBS. /// /// Name of the scene to remove public void RemoveScene(string sceneName) { var request = new JObject { { nameof(sceneName), sceneName } }; SendRequest(nameof(RemoveScene), request); } /// /// Sets the name of a scene (rename). /// /// Name of the scene to be renamed /// New name for the scene public void SetSceneName(string sceneName, string newSceneName) { var request = new JObject { { nameof(sceneName), sceneName }, { nameof(newSceneName), newSceneName } }; SendRequest(nameof(SetSceneName), request); } /// /// Gets a Base64-encoded screenshot of a source. /// The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. /// If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. /// **Compatible with inputs and scenes.** /// /// Name of the source to take a screenshot of /// Image compression format to use. Use `GetVersion` to get compatible image formats /// Width to scale the screenshot to /// Height to scale the screenshot to /// Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use \"default\" (whatever that means, idk) /// Base64-encoded screenshot public string GetSourceScreenshot(string sourceName, string imageFormat, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1) { var request = new JObject { { nameof(sourceName), sourceName }, { nameof(imageFormat), imageFormat } }; if (imageWidth > -1) { request.Add(nameof(imageWidth), imageWidth); } if (imageHeight > -1) { request.Add(nameof(imageHeight), imageHeight); } if (imageCompressionQuality > -1) { request.Add(nameof(imageCompressionQuality), imageCompressionQuality); } var response = SendRequest(nameof(GetSourceScreenshot), request); return (string)response["imageData"]; } /// /// Gets an array of all available transition kinds. /// Similar to `GetInputKindList` /// /// Array of transition kinds public List GetTransitionKindList() { var response = SendRequest(nameof(GetTransitionKindList)); return JsonConvert.DeserializeObject>(response["transitionKinds"].ToString()); } /// /// Gets the cursor position of the current scene transition. /// Note: `transitionCursor` will return 1.0 when the transition is inactive. /// /// Cursor position, between 0.0 and 1.0 public double GetCurrentSceneTransitionCursor() { var response = SendRequest(nameof(GetCurrentSceneTransitionCursor)); return (double)response["transitionCursor"]; } /// /// Opens the properties dialog of an input. /// /// Name of the input to open the dialog of public void OpenInputPropertiesDialog(string inputName) { var request = new JObject { { nameof(inputName), inputName } }; SendRequest(nameof(OpenInputPropertiesDialog), request); } /// /// Opens the filters dialog of an input. /// /// Name of the input to open the dialog of public void OpenInputFiltersDialog(string inputName) { var request = new JObject { { nameof(inputName), inputName } }; SendRequest(nameof(OpenInputFiltersDialog), request); } /// /// Opens the interact dialog of an input. /// /// Name of the input to open the dialog of public void OpenInputInteractDialog(string inputName) { var request = new JObject { { nameof(inputName), inputName } }; SendRequest(nameof(OpenInputInteractDialog), request); } /// /// Gets a list of connected monitors and information about them. /// /// a list of detected monitors with some information public List GetMonitorList() { var response = SendRequest(nameof(GetMonitorList)); var monitors = new List(); foreach(var monitor in response["monitors"]) { monitors.Add(new Monitor((JObject)monitor)); } return monitors; } /// /// Opens a projector for a source. /// Note: This request serves to provide feature parity with 4.x. It is very likely to be changed/deprecated in a future release. /// /// Name of the source to open a projector for /// Size/Position data for a windowed projector, in Qt Base64 encoded format. Mutually exclusive with monitorIndex /// Monitor index, use GetMonitorList to obtain index. -1 to open in windowed mode public void OpenSourceProjector(string sourceName, string projectorGeometry, int monitorIndex = -1) { var request = new JObject { { nameof(sourceName), sourceName }, { nameof(projectorGeometry), projectorGeometry }, { nameof(monitorIndex), monitorIndex }, }; SendRequest(nameof(OpenSourceProjector), request); } /// /// Opens a projector for a specific output video mix. /// Note: This request serves to provide feature parity with 4.x. It is very likely to be changed/deprecated in a future release. /// /// Mix types: OBS_WEBSOCKET_VIDEO_MIX_TYPE_PREVIEW, OBS_WEBSOCKET_VIDEO_MIX_TYPE_PROGRAM, OBS_WEBSOCKET_VIDEO_MIX_TYPE_MULTIVIEW /// Size/Position data for a windowed projector, in Qt Base64 encoded format. Mutually exclusive with monitorIndex /// Monitor index, use GetMonitorList to obtain index. -1 to open in windowed mode public void OpenVideoMixProjector(string videoMixType, string projectorGeometry, int monitorIndex = -1) { var request = new JObject { { nameof(videoMixType), videoMixType }, { nameof(projectorGeometry), projectorGeometry }, { nameof(monitorIndex), monitorIndex }, }; SendRequest(nameof(OpenVideoMixProjector), request); } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/CurrentPreviewSceneChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class CurrentPreviewSceneChangedEventArgs : EventArgs { /// /// Name of the scene that was switched to /// public string SceneName { get; } /// /// Default Constructor /// /// The scene name public CurrentPreviewSceneChangedEventArgs(string sceneName) { SceneName = sceneName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/CurrentProfileChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class CurrentProfileChangedEventArgs : EventArgs { /// /// Name of the new profile /// public string ProfileName { get; } /// /// Default Constructor /// /// The profile name public CurrentProfileChangedEventArgs(string profileName) { ProfileName = profileName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/CurrentProfileChangingEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class CurrentProfileChangingEventArgs : EventArgs { /// /// Name of the current profile /// public string ProfileName { get; } /// /// Default Constructor /// /// The profile name public CurrentProfileChangingEventArgs(string profileName) { ProfileName = profileName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/CurrentSceneCollectionChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class CurrentSceneCollectionChangedEventArgs : EventArgs { /// /// Name of the new scene collection /// public string SceneCollectionName { get; } /// /// Default Constructor /// /// The scene collection name public CurrentSceneCollectionChangedEventArgs(string sceneCollectionName) { SceneCollectionName = sceneCollectionName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/CurrentSceneCollectionChangingEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class CurrentSceneCollectionChangingEventArgs : EventArgs { /// /// Name of the current scene collection /// public string SceneCollectionName { get; } /// /// Default Constructor /// /// The scene collection name public CurrentSceneCollectionChangingEventArgs(string sceneCollectionName) { SceneCollectionName = sceneCollectionName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/CurrentSceneTransitionChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class CurrentSceneTransitionChangedEventArgs : EventArgs { /// /// Name of the new transition /// public string TransitionName { get; } /// /// Default Constructor /// /// The transition name public CurrentSceneTransitionChangedEventArgs(string transitionName) { TransitionName = transitionName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/CurrentSceneTransitionDurationChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class CurrentSceneTransitionDurationChangedEventArgs : EventArgs { /// /// Transition duration in milliseconds /// public int TransitionDuration { get; } /// /// Default Constructor /// /// The transition duration public CurrentSceneTransitionDurationChangedEventArgs(int transitionDuration) { TransitionDuration = transitionDuration; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputActiveStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputActiveStateChangedEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// Whether the input is active /// public bool VideoActive { get; } /// /// Default Constructor /// /// The input name /// Is the video active public InputActiveStateChangedEventArgs(string inputName, bool videoActive) { InputName = inputName; VideoActive = videoActive; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputAudioBalanceChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputAudioBalanceChangedEventArgs : EventArgs { /// /// Name of the affected input /// public string InputName { get; } /// /// New audio balance value of the input /// public double InputAudioBalance { get; } /// /// Default Constructor /// /// The input name /// The input audio balance public InputAudioBalanceChangedEventArgs(string inputName, double inputAudioBalance) { InputName = inputName; InputAudioBalance = inputAudioBalance; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputAudioMonitorTypeChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// Available types are: /// - `OBS_MONITORING_TYPE_NONE` /// - `OBS_MONITORING_TYPE_MONITOR_ONLY` /// - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` /// public class InputAudioMonitorTypeChangedEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// New monitor type of the input /// public string MonitorType { get; } /// /// Default Constructor /// /// The input name /// The monitor type public InputAudioMonitorTypeChangedEventArgs(string inputName, string monitorType) { InputName = inputName; MonitorType = monitorType; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputAudioSyncOffsetChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputAudioSyncOffsetChangedEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// New sync offset in milliseconds /// public int InputAudioSyncOffset { get; } /// /// Default Constructor /// /// The input name /// The input audio sync offset public InputAudioSyncOffsetChangedEventArgs(string inputName, int inputAudioSyncOffset) { InputName = inputName; InputAudioSyncOffset = inputAudioSyncOffset; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputAudioTracksChangedEventArgs.cs ================================================ using System; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputAudioTracksChangedEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// Object of audio tracks along with their associated enable states /// public JObject InputAudioTracks {get;} /// /// Default Constructor /// /// The input name /// The audio track data as a JObject public InputAudioTracksChangedEventArgs(string inputName, JObject inputAudioTracks) { InputName = inputName; InputAudioTracks = inputAudioTracks; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputCreatedEventArgs.cs ================================================ using System; using Newtonsoft.Json.Linq; using OBSWebsocketDotNet; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputCreatedEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// The kind of the input /// public string InputKind { get; } /// /// The unversioned kind of input (aka no `_v2` stuff) /// public string UnversionedInputKind { get; } /// /// The settings configured to the input when it was created /// public JObject InputSettings { get; } /// /// The default settings for the input /// public JObject DefaultInputSettings { get; } /// /// Default Constructor /// /// The input name /// The kind of input /// The unversioned kind of input /// The input settings as a JObject /// The default input settings as a JObject public InputCreatedEventArgs(string inputName, string inputKind, string unversionedInputKind, JObject inputSettings, JObject defaultInputSettings) { InputName = inputName; InputKind = inputKind; UnversionedInputKind = unversionedInputKind; InputSettings = inputSettings; DefaultInputSettings = defaultInputSettings; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputMuteStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputMuteStateChangedEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// Whether the input is muted /// public bool InputMuted { get; } /// /// Default Constructor /// /// The input name /// Is the input muted public InputMuteStateChangedEventArgs(string inputName, bool inputMuted) { InputName = inputName; InputMuted = inputMuted; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputNameChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputNameChangedEventArgs : EventArgs { /// /// Old name of the input /// public string OldInputName { get; } /// /// New name of the input /// public string InputName { get; } /// /// Default Constructor /// /// The old input name /// The new input name public InputNameChangedEventArgs(string oldInputName, string inputName) { OldInputName = oldInputName; InputName = inputName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputRemovedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputRemovedEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// Default Constructor /// /// The input name public InputRemovedEventArgs(string inputName) { InputName = inputName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputShowStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputShowStateChangedEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// Whether the input is showing /// public bool VideoShowing { get; } /// /// Default Constructor /// /// The input name /// Is the video showing public InputShowStateChangedEventArgs(string inputName, bool videoShowing) { InputName = inputName; VideoShowing = videoShowing; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputVolumeChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputVolumeChangedEventArgs : EventArgs { /// /// Current volume levels of source /// public InputVolume Volume { get; } /// /// Default Constructor /// /// The new input volume public InputVolumeChangedEventArgs(InputVolume volume) { Volume = volume; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/InputVolumeMetersEventArgs.cs ================================================ using System; using System.Collections.Generic; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class InputVolumeMetersEventArgs : EventArgs { /// /// Array of active inputs with their associated volume levels /// public List inputs { get; } /// /// Default Constructor /// /// Collection inputs as JObjects public InputVolumeMetersEventArgs(List inputs) { this.inputs = inputs; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/MediaInputActionTriggeredEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class MediaInputActionTriggeredEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// Action performed on the input. See `ObsMediaInputAction` enum /// public string MediaAction { get; } /// /// Default Constructor /// /// The input name /// The media action data public MediaInputActionTriggeredEventArgs(string inputName, string mediaAction) { InputName = inputName; MediaAction = mediaAction; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/MediaInputPlaybackEndedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class MediaInputPlaybackEndedEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// Default Constructor /// /// The input name public MediaInputPlaybackEndedEventArgs(string inputName) { InputName = inputName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/MediaInputPlaybackStartedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class MediaInputPlaybackStartedEventArgs : EventArgs { /// /// Name of the input /// public string InputName { get; } /// /// Default Constructor /// /// The input name public MediaInputPlaybackStartedEventArgs(string inputName) { InputName = inputName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/ProfileListChangedEventArgs.cs ================================================ using System; using System.Collections.Generic; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class ProfileListChangedEventArgs : EventArgs { /// /// The profiles that have changed /// public List Profiles { get; } /// /// Default Constructor /// /// Collection of profile names as strings public ProfileListChangedEventArgs(List profiles) { Profiles = profiles; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/ProgramSceneChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class ProgramSceneChangedEventArgs : EventArgs { /// /// The new scene name /// public string SceneName { get; } /// /// Default Constructor /// /// The scene name public ProgramSceneChangedEventArgs(string sceneName) { SceneName = sceneName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/RecordStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class RecordStateChangedEventArgs : EventArgs { /// /// The specific state of the output /// public RecordStateChanged OutputState { get; } /// /// Default Constructor /// /// The record state change data public RecordStateChangedEventArgs(RecordStateChanged outputState) { OutputState = outputState; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/ReplayBufferSavedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class ReplayBufferSavedEventArgs : EventArgs { /// /// Path of the saved replay file /// public string SavedReplayPath { get; } /// /// Default Constructor /// /// The saved replay path public ReplayBufferSavedEventArgs(string savedReplayPath) { SavedReplayPath = savedReplayPath; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/ReplayBufferStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class ReplayBufferStateChangedEventArgs : EventArgs { /// /// The specific state of the output /// public OutputStateChanged OutputState { get; } /// /// Default constructor /// /// Specific state of the output public ReplayBufferStateChangedEventArgs(OutputStateChanged outputState) { OutputState = outputState; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneCollectionListChangedEventArgs.cs ================================================ using System; using System.Collections.Generic; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneCollectionListChangedEventArgs : EventArgs { /// /// Updated list of scene collections /// public List SceneCollections { get; } /// /// Default Constructor /// /// Collection of scene collection names as string public SceneCollectionListChangedEventArgs(List sceneCollections) { SceneCollections = sceneCollections; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneCreatedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneCreatedEventArgs : EventArgs { /// /// Name of the new scene /// public string SceneName { get; } /// /// Whether the new scene is a group /// public bool IsGroup { get; } /// /// Default Constructor /// /// The scene name /// Is the scene item a group public SceneCreatedEventArgs(string sceneName, bool isGroup) { SceneName = sceneName; IsGroup = isGroup; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneItemCreatedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneItemCreatedEventArgs : EventArgs { /// /// Name of the scene where the item is /// public string SceneName { get; } /// /// Name of the concerned item /// public string SourceName { get; } /// /// Numeric ID of the scene item /// public int SceneItemId { get; } /// /// Index position of the item /// public int SceneItemIndex { get; } /// /// Default Constructor /// /// The scene name /// The source name /// The scene item id /// The scene item index public SceneItemCreatedEventArgs(string sceneName, string sourceName, int sceneItemId, int sceneItemIndex) { SceneName = sceneName; SourceName = sourceName; SceneItemId = sceneItemId; SceneItemIndex = sceneItemIndex; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneItemEnableStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneItemEnableStateChangedEventArgs : EventArgs { /// /// Name of the scene the item is in /// public string SceneName { get; } /// /// Numeric ID of the scene item /// public int SceneItemId { get; } /// /// Whether the scene item is enabled (visible) /// public bool SceneItemEnabled { get; } /// /// Default Constructor /// /// The scene name /// The scene item id /// Is the scene item enabled public SceneItemEnableStateChangedEventArgs(string sceneName, int sceneItemId, bool sceneItemEnabled) { SceneName = sceneName; SceneItemId = sceneItemId; SceneItemEnabled = sceneItemEnabled; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneItemListReindexedEventArgs.cs ================================================ using System; using System.Collections.Generic; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneItemListReindexedEventArgs : EventArgs { /// /// Name of the scene where items where reordered /// public string SceneName { get; } /// /// List of all scene items as JObject /// public List SceneItems { get; } /// /// Default Constructor /// /// The scene name /// The scene item data as a colleciton of JObjects public SceneItemListReindexedEventArgs(string sceneName, List sceneItems) { SceneName = sceneName; SceneItems = sceneItems; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneItemLockStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneItemLockStateChangedEventArgs : EventArgs { /// /// Name of the scene the item is in /// public string SceneName { get; } /// /// Numeric ID of the scene item /// public int SceneItemId { get; } /// /// Whether the scene item is locked (visible) /// public bool SceneItemLocked { get; } /// /// Default Constructor /// /// The scene name /// The scene item id /// is the scene item locked public SceneItemLockStateChangedEventArgs(string sceneName, int sceneItemId, bool sceneItemLocked) { SceneName = sceneName; SceneItemId = sceneItemId; SceneItemLocked = sceneItemLocked; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneItemRemovedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneItemRemovedEventArgs : EventArgs { /// /// Name of the scene where the item was removed from /// public string SceneName { get; } /// /// Name of the concerned item /// public string SourceName { get; } /// /// Numeric ID of the scene item /// public int SceneItemId { get; } /// /// Default Constructor /// /// The scene name /// The source name /// The scene items id public SceneItemRemovedEventArgs(string sceneName, string sourceName, int sceneItemId) { SceneName = sceneName; SourceName = sourceName; SceneItemId = sceneItemId; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneItemSelectedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneItemSelectedEventArgs : EventArgs { /// /// Name of the scene item is in /// public string SceneName { get; } /// /// Numeric ID of the scene item /// public string SceneItemId { get; } /// /// Default Constructor /// /// The scene name /// The scene item id public SceneItemSelectedEventArgs(string sceneName, string sceneItemId) { SceneName = sceneName; SceneItemId = sceneItemId; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneItemTransformEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneItemTransformEventArgs : EventArgs { /// /// Name of the scene item is in /// public string SceneName { get; } /// /// Numeric ID of the scene item /// public string SceneItemId { get; } /// /// Transform data /// public SceneItemTransformInfo Transform { get; } /// /// Default Constructor /// /// The scene name /// The scene item id /// The transform data public SceneItemTransformEventArgs(string sceneName, string sceneItemId, SceneItemTransformInfo transform) { SceneName = sceneName; SceneItemId = sceneItemId; Transform = transform; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneListChangedEventArgs.cs ================================================ using System; using System.Collections.Generic; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneListChangedEventArgs : EventArgs { /// /// Updated array of scenes /// public List Scenes { get; } /// /// Default Constructor /// /// Collection of scene data as JObjects public SceneListChangedEventArgs(List scenes) { Scenes = scenes; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneNameChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneNameChangedEventArgs : EventArgs { /// /// Old name of the scene /// public string OldSceneName { get; } /// /// New name of the scene /// public string SceneName { get; } /// /// Default Constructor /// /// The previous scene name /// The new scene name public SceneNameChangedEventArgs(string oldSceneName, string sceneName) { OldSceneName = oldSceneName; SceneName = sceneName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneRemovedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneRemovedEventArgs : EventArgs { /// /// Name of the removed scene /// public string SceneName { get; } /// /// Whether the removed scene was a group /// public bool IsGroup { get; } /// /// Default Constructor /// /// The scene name /// Is the scene name a group public SceneRemovedEventArgs(string sceneName, bool isGroup) { SceneName = sceneName; IsGroup = isGroup; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneTransitionEndedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneTransitionEndedEventArgs : EventArgs { /// /// Scene transition name /// public string TransitionName { get; } /// /// Default Constructor /// /// The transition name public SceneTransitionEndedEventArgs(string transitionName) { TransitionName = transitionName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneTransitionStartedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SceneTransitionStartedEventArgs : EventArgs { /// /// Transition name /// public string TransitionName { get; } /// /// Default Constructor /// /// The transition name public SceneTransitionStartedEventArgs(string transitionName) { TransitionName = transitionName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SceneTransitionVideoEndedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Called by /// public class SceneTransitionVideoEndedEventArgs : EventArgs { /// /// Transition name /// public string TransitionName { get; } /// /// Default Constructor /// /// The transition name public SceneTransitionVideoEndedEventArgs(string transitionName) { TransitionName = transitionName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SourceFilterCreatedEventArgs.cs ================================================ using System; using Newtonsoft.Json.Linq; using OBSWebsocketDotNet; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SourceFilterCreatedEventArgs : EventArgs { /// /// Name of the source the filter was added to /// public string SourceName { get; } /// /// Name of the filter /// public string FilterName{ get; } /// /// The kind of the filter /// public string FilterKind{ get; } /// /// Index position of the filter /// public int FilterIndex{ get; } /// /// The settings configured to the filter when it was created /// public JObject FilterSettings{ get; } /// /// The default settings for the filter /// public JObject DefaultFilterSettings { get; } /// /// Default Constructor /// /// The source name /// The filter name /// The kind of filter /// The index of the filter /// The filters settings as a JObject /// The default filter settings as a JObject public SourceFilterCreatedEventArgs(string sourceName, string filterName, string filterKind, int filterIndex, JObject filterSettings, JObject defaultFilterSettings) { SourceName = sourceName; FilterName = filterName; FilterKind = filterKind; FilterIndex = filterIndex; FilterSettings = filterSettings; DefaultFilterSettings = defaultFilterSettings; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SourceFilterEnableStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SourceFilterEnableStateChangedEventArgs : EventArgs { /// /// Name of the source the filter is on /// public string SourceName { get; } /// /// Name of the filter /// public string FilterName { get; } /// /// Whether the filter is enabled /// public bool FilterEnabled { get; } /// /// Default Constructor /// /// The source name /// The filter name /// If the filter is enabled or not public SourceFilterEnableStateChangedEventArgs(string sourceName, string filterName, bool filterEnabled) { SourceName = sourceName; FilterName = filterName; FilterEnabled = filterEnabled; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SourceFilterListReindexedEventArgs.cs ================================================ using System; using System.Collections.Generic; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SourceFilterListReindexedEventArgs : EventArgs { /// /// Name of the source /// public string SourceName { get; } /// /// Array of filter objects /// public List Filters { get; } /// /// Default Constructor /// /// The source name /// Collection of filters public SourceFilterListReindexedEventArgs(string sourceName, List filters) { SourceName = sourceName; Filters = filters; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SourceFilterNameChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SourceFilterNameChangedEventArgs : EventArgs { /// /// The source the filter is on /// public string SourceName { get; } /// /// Old name of the filter /// public string OldFilterName { get; } /// /// New name of the filter /// public string FilterName { get; } /// /// Default Constructor /// /// The source name /// The filters previous name /// The filters new name public SourceFilterNameChangedEventArgs(string sourceName, string oldFilterName, string filterName) { SourceName = sourceName; OldFilterName = oldFilterName; FilterName = filterName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/SourceFilterRemovedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class SourceFilterRemovedEventArgs : EventArgs { /// /// Name of the source the filter was on /// public string SourceName { get; } /// /// Name of the filter /// public string FilterName { get; } /// /// Default Constructor /// /// The source name /// The filter name that's been removed public SourceFilterRemovedEventArgs(string sourceName, string filterName) { SourceName = sourceName; FilterName = filterName; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/StreamStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class StreamStateChangedEventArgs : EventArgs { /// /// The specific state of the output /// public OutputStateChanged OutputState { get; } /// /// Default Constructor /// /// The output state data public StreamStateChangedEventArgs(OutputStateChanged outputState) { OutputState = outputState; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/StudioModeStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class StudioModeStateChangedEventArgs : EventArgs { /// /// New Studio Mode status /// public bool StudioModeEnabled { get; } /// /// Default Constructor /// /// Is studio mode enabled public StudioModeStateChangedEventArgs(bool studioModeEnabled) { StudioModeEnabled = studioModeEnabled; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/UnsupportedEventArgs.cs ================================================ using System; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for unsupported events /// public class UnsupportedEventArgs : EventArgs { /// /// The type of the event /// public string EventType { get; } /// /// The body of the event /// public JObject Body { get; } /// /// Event args for unsupported events /// public UnsupportedEventArgs(string eventType, JObject body) { EventType = eventType; Body = body; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/VendorEventArgs.cs ================================================ using System; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class VendorEventArgs : EventArgs { /// /// Name of the vendor emitting the event /// public string VendorName { get; } /// /// Vendor-provided event typedef /// public string EventType { get; } /// /// Vendor-provided event data. {} if event does not provide any data /// public JObject eventData { get; } /// /// Default Constructor /// /// The vendor name /// The event type /// The event data as a Json Object public VendorEventArgs(string vendorName, string eventType, JObject eventData) { VendorName = vendorName; EventType = eventType; this.eventData = eventData; } } } ================================================ FILE: obs-websocket-dotnet/Types/Events/VirtualcamStateChangedEventArgs.cs ================================================ using System; namespace OBSWebsocketDotNet.Types.Events { /// /// Event args for /// public class VirtualcamStateChangedEventArgs : EventArgs { /// /// The specific state of the output /// public OutputStateChanged OutputState { get; } /// /// Default Constructor /// /// The output state data public VirtualcamStateChangedEventArgs(OutputStateChanged outputState) { OutputState = outputState; } } } ================================================ FILE: obs-websocket-dotnet/Types/FilterReorderItem.cs ================================================ using Newtonsoft.Json; namespace OBSWebsocketDotNet.Types { /// /// Filter list item /// public class FilterReorderItem { /// /// Name of filter /// [JsonProperty(PropertyName = "name")] public string Name { set; get; } /// /// Type of filter /// [JsonProperty(PropertyName = "type")] public string Type { set; get; } } } ================================================ FILE: obs-websocket-dotnet/Types/FilterSettings.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Filter settings /// public class FilterSettings { /// /// Name of the filter /// [JsonProperty(PropertyName = "filterName")] public string Name { set; get; } /// /// Type of the specified filter /// [JsonProperty(PropertyName = "filterKind")] public string Kind { set; get; } /// /// Index of the filter in the list, beginning at 0 /// [JsonProperty(PropertyName = "filterIndex")] public int Index { get; set; } /// /// Status of the specified filter /// [JsonProperty(PropertyName = "filterEnabled")] public bool IsEnabled { set; get; } /// /// Settings for the filter /// [JsonProperty(PropertyName = "filterSettings")] public JObject Settings { set; get; } } } ================================================ FILE: obs-websocket-dotnet/Types/GetProfileListInfo.cs ================================================ using Newtonsoft.Json; using System.Collections.Generic; namespace OBSWebsocketDotNet.Types { /// /// Response from /// public class GetProfileListInfo { /// /// Name of the currently active profile /// [JsonProperty(PropertyName = "currentProfileName")] public string CurrentProfileName { set; get; } /// /// List of all profiles /// [JsonProperty(PropertyName = "profiles")] public List Profiles { set; get; } } } ================================================ FILE: obs-websocket-dotnet/Types/GetSceneListInfo.cs ================================================ using Newtonsoft.Json; using System.Collections.Generic; namespace OBSWebsocketDotNet.Types { /// /// Response from /// public class GetSceneListInfo { /// /// Name of the currently active program scene /// [JsonProperty(PropertyName = "currentProgramSceneName")] public string CurrentProgramSceneName { set; get; } /// /// Name of the currently active preview/studio scene /// Note: Will return null if not in studio mode /// [JsonProperty(PropertyName = "currentPreviewSceneName")] public string CurrentPreviewSceneName { set; get; } /// /// Ordered list of the current profile's scenes /// [JsonProperty(PropertyName = "scenes")] public List Scenes { set; get; } } } ================================================ FILE: obs-websocket-dotnet/Types/GetTransitionListInfo.cs ================================================ using Newtonsoft.Json; using System.Collections.Generic; namespace OBSWebsocketDotNet.Types { /// /// Response from /// public class GetTransitionListInfo { /// /// Name of the currently active transition /// [JsonProperty(PropertyName = "currentSceneTransitionName")] public string CurrentTransition { set; get; } /// /// Kind of the currently active transition /// [JsonProperty(PropertyName = "currentSceneTransitionKind")] public string CurrentTransitionKing { set; get; } /// /// List of transitions. /// [JsonProperty(PropertyName = "transitions")] public List Transitions { set; get; } } } ================================================ FILE: obs-websocket-dotnet/Types/Input.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Abstract class with information on a specific Input /// public abstract class Input { /// /// Name of the Input /// [JsonProperty(PropertyName = "inputName")] public string InputName { get; set; } /// /// Kind of the Input /// [JsonProperty(PropertyName = "inputKind")] public string InputKind { get; set; } /// /// Instantiate object from response data /// /// public Input(JObject body) { JsonConvert.PopulateObject(body.ToString(), this); } /// /// Default Constructor /// public Input() { } } } ================================================ FILE: obs-websocket-dotnet/Types/InputBasicInfo.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Text; namespace OBSWebsocketDotNet.Types { /// /// Input class which also shows the Unversioned Input Kind /// public class InputBasicInfo : Input { /// /// Unversioned Kind of the Input /// [JsonProperty(PropertyName = "unversionedInputKind")] public string UnversionedKind { get; set; } /// /// Instantiate object from response data /// /// public InputBasicInfo(JObject body) : base(body) { JsonConvert.PopulateObject(body.ToString(), this); } /// /// Default Constructor /// public InputBasicInfo() { } } } ================================================ FILE: obs-websocket-dotnet/Types/InputBrowserSourceSettings.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Text; namespace OBSWebsocketDotNet.Types { /// /// Input class dedicated for the ffmpeg_source input kind. /// Usage: InputBrowserSourceSettings.FromInputSettings(InputSettings) /// public class InputBrowserSourceSettings : Input { private const string SUPPORTED_INPUT_KIND = "browser_source"; private const string CSS_DEFAULT_VALUE = "body { background-color: rgba(0, 0, 0, 0); margin: 0px auto; overflow: hidden; }"; /// /// Set a custom FPS (using the FPS property) /// [JsonProperty(PropertyName = "fps_custom")] public bool CustomFPS { get; set; } = false; /// /// Frames Per Second /// [JsonProperty(PropertyName = "fps")] public int FPS { get; set; } = 30; /// /// Control audio via OBS /// [JsonProperty(PropertyName = "reroute_audio")] public bool RerouteAudio { get; set; } = false; /// /// Height /// [JsonProperty(PropertyName = "height")] public int Height { get; set; } = 600; /// /// Width /// [JsonProperty(PropertyName = "width")] public int Width { get; set; } = 800; /// /// Custom CSS /// [JsonProperty(PropertyName = "css")] public string CSS { get; set; } = CSS_DEFAULT_VALUE; /// /// Is Local file /// [JsonProperty(PropertyName = "is_local_file")] public bool IsLocalFile { get; set; } = false; /// /// Local filename (when IsLocalFile is true) /// [JsonProperty(PropertyName = "local_file")] public string LocalFile { get; set; } /// /// URL (when IsLocalFile is false) /// [JsonProperty(PropertyName = "url")] public string URL { get; set; } /// /// Refresh browser when scene becomes active /// [JsonProperty(PropertyName = "restart_when_active")] public bool RestartWhenActive { get; set; } = false; /// /// Shutdown source when not visible /// [JsonProperty(PropertyName = "shutdown")] public bool ShutdownWhenNotVisible { get; set; } = false; /// /// Page Permissions /// [JsonProperty(PropertyName = "webpage_control_level")] public int ControlLevel { get; set; } = 1; /// /// Static constructor to instanciate a InputBrowserSourceSettings object /// Requires an InputSettings class with InputKind of browser_source to create /// /// Settings object /// public static InputBrowserSourceSettings FromInputSettings(InputSettings settings) { return new InputBrowserSourceSettings(settings); } // Private Constrctor private InputBrowserSourceSettings(InputSettings settings) : base(JObject.FromObject(settings)) { if (settings.InputKind != SUPPORTED_INPUT_KIND) { throw new InvalidCastException(); } JsonConvert.PopulateObject(settings.Settings.ToString(), this); } } } ================================================ FILE: obs-websocket-dotnet/Types/InputFFMpegSettings.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Text; namespace OBSWebsocketDotNet.Types { /// /// Input class dedicated for the ffmpeg_source input kind. /// Usage: InputFFMpegSettings.FromInputSettings(InputSettings) /// public class InputFFMpegSettings : Input { private const string SUPPORTED_INPUT_KIND = "ffmpeg_source"; /// /// Buffering MB /// [JsonProperty(PropertyName = "buffering_mb")] public int BufferingMB { get; set; } = 2; /// /// Clear window when media ends /// [JsonProperty(PropertyName = "clear_on_media_end")] public bool ClearOnMediaEnd { get; set; } = true; /// /// Close when inactive /// [JsonProperty(PropertyName = "close_when_inactive")] public bool CloseWhenInactive { get; set; } = false; /// /// Color Range /// [JsonProperty(PropertyName = "color_range")] public int ColorRange { get; set; } = 0; /// /// HW Decoder /// [JsonProperty(PropertyName = "hw_decode")] public bool HWDecode { get; set; } = false; /// /// Is Local file /// [JsonProperty(PropertyName = "is_local_file")] public bool IsLocalFile { get; set; } = true; /// /// Local filename /// [JsonProperty(PropertyName = "local_file")] public string LocalFile { get; set; } /// /// Looping /// [JsonProperty(PropertyName = "looping")] public bool Looping { get; set; } = false; /// /// Apply alpha in linear space /// [JsonProperty(PropertyName = "linear_alpha")] public bool LinearAlpha { get; set; } = false; /// /// Restart when activated /// [JsonProperty(PropertyName = "restart_on_activate")] public bool RestartOnActivate { get; set; } = true; /// /// ffmpeg options /// [JsonProperty(PropertyName = "ffmpeg_options")] public string Options { get; set; } /// /// Speed percentage /// [JsonProperty(PropertyName = "speed_percent")] public int SpeedPercent { get; set; } = 100; /// /// Static constructor to instanciate a InputFFMpegSettings object /// Requires an InputSettings class with InputKind of ffmpeg_source to create /// /// Setings object /// public static InputFFMpegSettings FromInputSettings(InputSettings settings) { return new InputFFMpegSettings(settings); } // Private Constrctor private InputFFMpegSettings(InputSettings settings) : base(JObject.FromObject(settings)) { if (settings.InputKind != SUPPORTED_INPUT_KIND) { throw new InvalidCastException(); } JsonConvert.PopulateObject(settings.Settings.ToString(), this); } } } ================================================ FILE: obs-websocket-dotnet/Types/InputSettings.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Settings for a source item /// public class InputSettings : Input { /// /// Settings for the source /// [JsonProperty(PropertyName = "inputSettings")] public JObject Settings { set; get; } /// /// Builds the object from the JSON data /// /// JSON item description as a public InputSettings(JObject data) : base(data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Default Constructor for deserialization /// public InputSettings() { } } } ================================================ FILE: obs-websocket-dotnet/Types/InputVolume.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Source volume values /// public class InputVolume { /// /// Name of the source /// [JsonProperty(PropertyName = "inputName")] public string InputName { set; get; } /// /// The source volume in percent /// [JsonProperty(PropertyName = "inputVolumeMul")] public float InputVolumeMul { get; set; } /// /// The source volume in decibels /// [JsonProperty(PropertyName = "inputVolumeDb")] public float InputVolumeDb { get; set; } /// /// Builds the object from the JSON response body /// /// JSON response body as a public InputVolume(JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Empty constructor for jsonconvert /// public InputVolume() { } } } ================================================ FILE: obs-websocket-dotnet/Types/KeyModifier.cs ================================================ using System; namespace OBSWebsocketDotNet.Types { /// /// Key Modifiers /// [Flags] public enum KeyModifier { /// /// No modifiers /// None = 0b_0000_0000, // 0 /// /// Shift Key /// Shift = 0b_0000_0001, // 1 /// /// Alt Key /// Alt = 0b_0000_0010, // 2 /// /// Control Key /// Control = 0b_0000_0100, // 4, /// /// Command (Mac) / WinKey (?) Windows /// Command = 0b_0000_1000 // 8 } } ================================================ FILE: obs-websocket-dotnet/Types/MediaInputStatus.cs ================================================ using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Status of a Media Input /// public class MediaInputStatus { /// /// State of the media input /// [JsonProperty(PropertyName = "mediaState")] public string StateString { get; set; } /// /// State of the media input /// [JsonIgnore] public MediaState? State { get { if (!Enum.TryParse(StateString, out MediaState state)) { return null; } return state; } } /// /// Total duration of the playing media in milliseconds. `null` if not playing /// [JsonProperty(PropertyName = "mediaDuration")] public long? Duration { get; set; } /// /// Position of the cursor in milliseconds. `null` if not playing /// [JsonProperty(PropertyName = "mediaCursor")] public long? Cursor { get; set; } /// /// Instantiate from JObject /// /// public MediaInputStatus(JObject body) { JsonConvert.PopulateObject(body.ToString(), this); } /// /// Default Constructor /// public MediaInputStatus() { } } /// /// Enum representing the state of a media input /// public enum MediaState { /// /// No media is loaded /// OBS_MEDIA_STATE_NONE, /// /// Media is playing /// OBS_MEDIA_STATE_PLAYING, /// /// Media is opening /// OBS_MEDIA_STATE_OPENING, /// /// Media is buffering /// OBS_MEDIA_STATE_BUFFERING, /// /// Media is playing but is paused /// OBS_MEDIA_STATE_PAUSED, /// /// Media is stopped /// OBS_MEDIA_STATE_STOPPED, /// /// Media is ended /// OBS_MEDIA_STATE_ENDED, /// /// Media has errored /// OBS_MEDIA_STATE_ERROR } } ================================================ FILE: obs-websocket-dotnet/Types/Monitor.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Information on a connected Monitor /// public class Monitor { /// /// Monitor height (px) /// [JsonProperty(PropertyName = "monitorHeight")] public int Height { get; set; } /// /// Monitor width (px) /// [JsonProperty(PropertyName = "monitorWidth")] public int Width { get; set; } /// /// Monitor Name /// [JsonProperty(PropertyName = "monitorName")] public string Name { get; set; } /// /// Monitor Index /// [JsonProperty(PropertyName = "monitorIndex")] public int Index { get; set; } /// /// Monitor Position X /// [JsonProperty(PropertyName = "monitorPositionX")] public int PositionX { get; set; } /// /// Monitor Position Y /// [JsonProperty(PropertyName = "monitorPositionY")] public int PositionY { get; set; } /// /// Constructor to auto populate /// /// public Monitor (JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Default Constructor /// public Monitor() { } } } ================================================ FILE: obs-websocket-dotnet/Types/OBSHotkey.cs ================================================ namespace OBSWebsocketDotNet.Types { /// /// OBS Hotkeys as defined here: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-hotkeys.h /// public enum OBSHotkey { #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member OBS_KEY_NONE, OBS_KEY_RETURN, OBS_KEY_ENTER, OBS_KEY_ESCAPE, OBS_KEY_TAB, OBS_KEY_BACKTAB, OBS_KEY_BACKSPACE, OBS_KEY_INSERT, OBS_KEY_DELETE, OBS_KEY_PAUSE, OBS_KEY_PRINT, OBS_KEY_SYSREQ, OBS_KEY_CLEAR, OBS_KEY_HOME, OBS_KEY_END, OBS_KEY_LEFT, OBS_KEY_UP, OBS_KEY_RIGHT, OBS_KEY_DOWN, OBS_KEY_PAGEUP, OBS_KEY_PAGEDOWN, OBS_KEY_SHIFT, OBS_KEY_CONTROL, OBS_KEY_META, OBS_KEY_ALT, OBS_KEY_ALTGR, OBS_KEY_CAPSLOCK, OBS_KEY_NUMLOCK, OBS_KEY_SCROLLLOCK, OBS_KEY_F1, OBS_KEY_F2, OBS_KEY_F3, OBS_KEY_F4, OBS_KEY_F5, OBS_KEY_F6, OBS_KEY_F7, OBS_KEY_F8, OBS_KEY_F9, OBS_KEY_F10, OBS_KEY_F11, OBS_KEY_F12, OBS_KEY_F13, OBS_KEY_F14, OBS_KEY_F15, OBS_KEY_F16, OBS_KEY_F17, OBS_KEY_F18, OBS_KEY_F19, OBS_KEY_F20, OBS_KEY_F21, OBS_KEY_F22, OBS_KEY_F23, OBS_KEY_F24, OBS_KEY_F25, OBS_KEY_F26, OBS_KEY_F27, OBS_KEY_F28, OBS_KEY_F29, OBS_KEY_F30, OBS_KEY_F31, OBS_KEY_F32, OBS_KEY_F33, OBS_KEY_F34, OBS_KEY_F35, OBS_KEY_MENU, OBS_KEY_HYPER_L, OBS_KEY_HYPER_R, OBS_KEY_HELP, OBS_KEY_DIRECTION_L, OBS_KEY_DIRECTION_R, OBS_KEY_SPACE, OBS_KEY_EXCLAM, OBS_KEY_QUOTEDBL, OBS_KEY_NUMBERSIGN, OBS_KEY_DOLLAR, OBS_KEY_PERCENT, OBS_KEY_AMPERSAND, OBS_KEY_APOSTROPHE, OBS_KEY_PARENLEFT, OBS_KEY_PARENRIGHT, OBS_KEY_ASTERISK, OBS_KEY_PLUS, OBS_KEY_COMMA, OBS_KEY_MINUS, OBS_KEY_PERIOD, OBS_KEY_SLASH, OBS_KEY_0, OBS_KEY_1, OBS_KEY_2, OBS_KEY_3, OBS_KEY_4, OBS_KEY_5, OBS_KEY_6, OBS_KEY_7, OBS_KEY_8, OBS_KEY_9, OBS_KEY_NUMEQUAL, OBS_KEY_NUMASTERISK, OBS_KEY_NUMPLUS, OBS_KEY_NUMCOMMA, OBS_KEY_NUMMINUS, OBS_KEY_NUMPERIOD, OBS_KEY_NUMSLASH, OBS_KEY_NUM0, OBS_KEY_NUM1, OBS_KEY_NUM2, OBS_KEY_NUM3, OBS_KEY_NUM4, OBS_KEY_NUM5, OBS_KEY_NUM6, OBS_KEY_NUM7, OBS_KEY_NUM8, OBS_KEY_NUM9, OBS_KEY_COLON, OBS_KEY_SEMICOLON, OBS_KEY_QUOTE, OBS_KEY_LESS, OBS_KEY_EQUAL, OBS_KEY_GREATER, OBS_KEY_QUESTION, OBS_KEY_AT, OBS_KEY_A, OBS_KEY_B, OBS_KEY_C, OBS_KEY_D, OBS_KEY_E, OBS_KEY_F, OBS_KEY_G, OBS_KEY_H, OBS_KEY_I, OBS_KEY_J, OBS_KEY_K, OBS_KEY_L, OBS_KEY_M, OBS_KEY_N, OBS_KEY_O, OBS_KEY_P, OBS_KEY_Q, OBS_KEY_R, OBS_KEY_S, OBS_KEY_T, OBS_KEY_U, OBS_KEY_V, OBS_KEY_W, OBS_KEY_X, OBS_KEY_Y, OBS_KEY_Z, OBS_KEY_BRACKETLEFT, OBS_KEY_BACKSLASH, OBS_KEY_BRACKETRIGHT, OBS_KEY_ASCIICIRCUM, OBS_KEY_UNDERSCORE, OBS_KEY_QUOTELEFT, OBS_KEY_BRACELEFT, OBS_KEY_BAR, OBS_KEY_BRACERIGHT, OBS_KEY_ASCIITILDE, OBS_KEY_NOBREAKSPACE, OBS_KEY_EXCLAMDOWN, OBS_KEY_CENT, OBS_KEY_STERLING, OBS_KEY_CURRENCY, OBS_KEY_YEN, OBS_KEY_BROKENBAR, OBS_KEY_SECTION, OBS_KEY_DIAERESIS, OBS_KEY_COPYRIGHT, OBS_KEY_ORDFEMININE, OBS_KEY_GUILLEMOTLEFT, OBS_KEY_NOTSIGN, OBS_KEY_HYPHEN, OBS_KEY_REGISTERED, OBS_KEY_MACRON, OBS_KEY_DEGREE, OBS_KEY_PLUSMINUS, OBS_KEY_TWOSUPERIOR, OBS_KEY_THREESUPERIOR, OBS_KEY_ACUTE, OBS_KEY_MU, OBS_KEY_PARAGRAPH, OBS_KEY_PERIODCENTERED, OBS_KEY_CEDILLA, OBS_KEY_ONESUPERIOR, OBS_KEY_MASCULINE, OBS_KEY_GUILLEMOTRIGHT, OBS_KEY_ONEQUARTER, OBS_KEY_ONEHALF, OBS_KEY_THREEQUARTERS, OBS_KEY_QUESTIONDOWN, OBS_KEY_AGRAVE, OBS_KEY_AACUTE, OBS_KEY_ACIRCUMFLEX, OBS_KEY_ATILDE, OBS_KEY_ADIAERESIS, OBS_KEY_ARING, OBS_KEY_AE, OBS_KEY_CCEDILLA, OBS_KEY_EGRAVE, OBS_KEY_EACUTE, OBS_KEY_ECIRCUMFLEX, OBS_KEY_EDIAERESIS, OBS_KEY_IGRAVE, OBS_KEY_IACUTE, OBS_KEY_ICIRCUMFLEX, OBS_KEY_IDIAERESIS, OBS_KEY_ETH, OBS_KEY_NTILDE, OBS_KEY_OGRAVE, OBS_KEY_OACUTE, OBS_KEY_OCIRCUMFLEX, OBS_KEY_OTILDE, OBS_KEY_ODIAERESIS, OBS_KEY_MULTIPLY, OBS_KEY_OOBLIQUE, OBS_KEY_UGRAVE, OBS_KEY_UACUTE, OBS_KEY_UCIRCUMFLEX, OBS_KEY_UDIAERESIS, OBS_KEY_YACUTE, OBS_KEY_THORN, OBS_KEY_SSHARP, OBS_KEY_DIVISION, OBS_KEY_YDIAERESIS, OBS_KEY_MULTI_KEY, OBS_KEY_CODEINPUT, OBS_KEY_SINGLECANDIDATE, OBS_KEY_MULTIPLECANDIDATE, OBS_KEY_PREVIOUSCANDIDATE, OBS_KEY_MODE_SWITCH, OBS_KEY_KANJI, OBS_KEY_MUHENKAN, OBS_KEY_HENKAN, OBS_KEY_ROMAJI, OBS_KEY_HIRAGANA, OBS_KEY_KATAKANA, OBS_KEY_HIRAGANA_KATAKANA, OBS_KEY_ZENKAKU, OBS_KEY_HANKAKU, OBS_KEY_ZENKAKU_HANKAKU, OBS_KEY_TOUROKU, OBS_KEY_MASSYO, OBS_KEY_KANA_LOCK, OBS_KEY_KANA_SHIFT, OBS_KEY_EISU_SHIFT, OBS_KEY_EISU_TOGGLE, OBS_KEY_HANGUL, OBS_KEY_HANGUL_START, OBS_KEY_HANGUL_END, OBS_KEY_HANGUL_HANJA, OBS_KEY_HANGUL_JAMO, OBS_KEY_HANGUL_ROMAJA, OBS_KEY_HANGUL_JEONJA, OBS_KEY_HANGUL_BANJA, OBS_KEY_HANGUL_PREHANJA, OBS_KEY_HANGUL_POSTHANJA, OBS_KEY_HANGUL_SPECIAL, OBS_KEY_DEAD_GRAVE, OBS_KEY_DEAD_ACUTE, OBS_KEY_DEAD_CIRCUMFLEX, OBS_KEY_DEAD_TILDE, OBS_KEY_DEAD_MACRON, OBS_KEY_DEAD_BREVE, OBS_KEY_DEAD_ABOVEDOT, OBS_KEY_DEAD_DIAERESIS, OBS_KEY_DEAD_ABOVERING, OBS_KEY_DEAD_DOUBLEACUTE, OBS_KEY_DEAD_CARON, OBS_KEY_DEAD_CEDILLA, OBS_KEY_DEAD_OGONEK, OBS_KEY_DEAD_IOTA, OBS_KEY_DEAD_VOICED_SOUND, OBS_KEY_DEAD_SEMIVOICED_SOUND, OBS_KEY_DEAD_BELOWDOT, OBS_KEY_DEAD_HOOK, OBS_KEY_DEAD_HORN, OBS_KEY_BACK, OBS_KEY_FORWARD, OBS_KEY_STOP, OBS_KEY_REFRESH, OBS_KEY_VOLUMEDOWN, OBS_KEY_VOLUMEMUTE, OBS_KEY_VOLUMEUP, OBS_KEY_BASSBOOST, OBS_KEY_BASSUP, OBS_KEY_BASSDOWN, OBS_KEY_TREBLEUP, OBS_KEY_TREBLEDOWN, OBS_KEY_MEDIAPLAY, OBS_KEY_MEDIASTOP, OBS_KEY_MEDIAPREVIOUS, OBS_KEY_MEDIANEXT, OBS_KEY_MEDIARECORD, OBS_KEY_MEDIAPAUSE, OBS_KEY_MEDIATOGGLEPLAYPAUSE, OBS_KEY_HOMEPAGE, OBS_KEY_FAVORITES, OBS_KEY_SEARCH, OBS_KEY_STANDBY, OBS_KEY_OPENURL, OBS_KEY_LAUNCHMAIL, OBS_KEY_LAUNCHMEDIA, OBS_KEY_LAUNCH0, OBS_KEY_LAUNCH1, OBS_KEY_LAUNCH2, OBS_KEY_LAUNCH3, OBS_KEY_LAUNCH4, OBS_KEY_LAUNCH5, OBS_KEY_LAUNCH6, OBS_KEY_LAUNCH7, OBS_KEY_LAUNCH8, OBS_KEY_LAUNCH9, OBS_KEY_LAUNCHA, OBS_KEY_LAUNCHB, OBS_KEY_LAUNCHC, OBS_KEY_LAUNCHD, OBS_KEY_LAUNCHE, OBS_KEY_LAUNCHF, OBS_KEY_LAUNCHG, OBS_KEY_LAUNCHH, OBS_KEY_MONBRIGHTNESSUP, OBS_KEY_MONBRIGHTNESSDOWN, OBS_KEY_KEYBOARDLIGHTONOFF, OBS_KEY_KEYBOARDBRIGHTNESSUP, OBS_KEY_KEYBOARDBRIGHTNESSDOWN, OBS_KEY_POWEROFF, OBS_KEY_WAKEUP, OBS_KEY_EJECT, OBS_KEY_SCREENSAVER, OBS_KEY_WWW, OBS_KEY_MEMO, OBS_KEY_LIGHTBULB, OBS_KEY_SHOP, OBS_KEY_HISTORY, OBS_KEY_ADDFAVORITE, OBS_KEY_HOTLINKS, OBS_KEY_BRIGHTNESSADJUST, OBS_KEY_FINANCE, OBS_KEY_COMMUNITY, OBS_KEY_AUDIOREWIND, OBS_KEY_BACKFORWARD, OBS_KEY_APPLICATIONLEFT, OBS_KEY_APPLICATIONRIGHT, OBS_KEY_BOOK, OBS_KEY_CD, OBS_KEY_CALCULATOR, OBS_KEY_TODOLIST, OBS_KEY_CLEARGRAB, OBS_KEY_CLOSE, OBS_KEY_COPY, OBS_KEY_CUT, OBS_KEY_DISPLAY, OBS_KEY_DOS, OBS_KEY_DOCUMENTS, OBS_KEY_EXCEL, OBS_KEY_EXPLORER, OBS_KEY_GAME, OBS_KEY_GO, OBS_KEY_ITOUCH, OBS_KEY_LOGOFF, OBS_KEY_MARKET, OBS_KEY_MEETING, OBS_KEY_MENUKB, OBS_KEY_MENUPB, OBS_KEY_MYSITES, OBS_KEY_NEWS, OBS_KEY_OFFICEHOME, OBS_KEY_OPTION, OBS_KEY_PASTE, OBS_KEY_PHONE, OBS_KEY_CALENDAR, OBS_KEY_REPLY, OBS_KEY_RELOAD, OBS_KEY_ROTATEWINDOWS, OBS_KEY_ROTATIONPB, OBS_KEY_ROTATIONKB, OBS_KEY_SAVE, OBS_KEY_SEND, OBS_KEY_SPELL, OBS_KEY_SPLITSCREEN, OBS_KEY_SUPPORT, OBS_KEY_TASKPANE, OBS_KEY_TERMINAL, OBS_KEY_TOOLS, OBS_KEY_TRAVEL, OBS_KEY_VIDEO, OBS_KEY_WORD, OBS_KEY_XFER, OBS_KEY_ZOOMIN, OBS_KEY_ZOOMOUT, OBS_KEY_AWAY, OBS_KEY_MESSENGER, OBS_KEY_WEBCAM, OBS_KEY_MAILFORWARD, OBS_KEY_PICTURES, OBS_KEY_MUSIC, OBS_KEY_BATTERY, OBS_KEY_BLUETOOTH, OBS_KEY_WLAN, OBS_KEY_UWB, OBS_KEY_AUDIOFORWARD, OBS_KEY_AUDIOREPEAT, OBS_KEY_AUDIORANDOMPLAY, OBS_KEY_SUBTITLE, OBS_KEY_AUDIOCYCLETRACK, OBS_KEY_TIME, OBS_KEY_HIBERNATE, OBS_KEY_VIEW, OBS_KEY_TOPMENU, OBS_KEY_POWERDOWN, OBS_KEY_SUSPEND, OBS_KEY_CONTRASTADJUST, OBS_KEY_MEDIALAST, OBS_KEY_CALL, OBS_KEY_CAMERA, OBS_KEY_CAMERAFOCUS, OBS_KEY_CONTEXT1, OBS_KEY_CONTEXT2, OBS_KEY_CONTEXT3, OBS_KEY_CONTEXT4, OBS_KEY_FLIP, OBS_KEY_HANGUP, OBS_KEY_NO, OBS_KEY_SELECT, OBS_KEY_YES, OBS_KEY_TOGGLECALLHANGUP, OBS_KEY_VOICEDIAL, OBS_KEY_LASTNUMBERREDIAL, OBS_KEY_EXECUTE, OBS_KEY_PRINTER, OBS_KEY_PLAY, OBS_KEY_SLEEP, OBS_KEY_ZOOM, OBS_KEY_CANCEL, OBS_KEY_BACKSLASH_RT102, OBS_KEY_OPEN, OBS_KEY_FIND, OBS_KEY_REDO, OBS_KEY_UNDO, OBS_KEY_FRONT, OBS_KEY_PROPS, OBS_KEY_VK_CANCEL, OBS_KEY_0x07, OBS_KEY_0x0A, OBS_KEY_0x0B, OBS_KEY_0x0E, OBS_KEY_0x0F, OBS_KEY_0x16, OBS_KEY_VK_JUNJA, OBS_KEY_VK_FINAL, OBS_KEY_0x1A, OBS_KEY_VK_ACCEPT, OBS_KEY_VK_MODECHANGE, OBS_KEY_VK_SELECT, OBS_KEY_VK_PRINT, OBS_KEY_VK_EXECUTE, OBS_KEY_VK_HELP, OBS_KEY_0x30, OBS_KEY_0x31, OBS_KEY_0x32, OBS_KEY_0x33, OBS_KEY_0x34, OBS_KEY_0x35, OBS_KEY_0x36, OBS_KEY_0x37, OBS_KEY_0x38, OBS_KEY_0x39, OBS_KEY_0x3A, OBS_KEY_0x3B, OBS_KEY_0x3C, OBS_KEY_0x3D, OBS_KEY_0x3E, OBS_KEY_0x3F, OBS_KEY_0x40, OBS_KEY_0x41, OBS_KEY_0x42, OBS_KEY_0x43, OBS_KEY_0x44, OBS_KEY_0x45, OBS_KEY_0x46, OBS_KEY_0x47, OBS_KEY_0x48, OBS_KEY_0x49, OBS_KEY_0x4A, OBS_KEY_0x4B, OBS_KEY_0x4C, OBS_KEY_0x4D, OBS_KEY_0x4E, OBS_KEY_0x4F, OBS_KEY_0x50, OBS_KEY_0x51, OBS_KEY_0x52, OBS_KEY_0x53, OBS_KEY_0x54, OBS_KEY_0x55, OBS_KEY_0x56, OBS_KEY_0x57, OBS_KEY_0x58, OBS_KEY_0x59, OBS_KEY_0x5A, OBS_KEY_VK_LWIN, OBS_KEY_VK_RWIN, OBS_KEY_VK_APPS, OBS_KEY_0x5E, OBS_KEY_VK_SLEEP, OBS_KEY_VK_SEPARATOR, OBS_KEY_0x88, OBS_KEY_0x89, OBS_KEY_0x8A, OBS_KEY_0x8B, OBS_KEY_0x8C, OBS_KEY_0x8D, OBS_KEY_0x8E, OBS_KEY_0x8F, OBS_KEY_VK_OEM_FJ_JISHO, OBS_KEY_VK_OEM_FJ_LOYA, OBS_KEY_VK_OEM_FJ_ROYA, OBS_KEY_0x97, OBS_KEY_0x98, OBS_KEY_0x99, OBS_KEY_0x9A, OBS_KEY_0x9B, OBS_KEY_0x9C, OBS_KEY_0x9D, OBS_KEY_0x9E, OBS_KEY_0x9F, OBS_KEY_VK_LSHIFT, OBS_KEY_VK_RSHIFT, OBS_KEY_VK_LCONTROL, OBS_KEY_VK_RCONTROL, OBS_KEY_VK_LMENU, OBS_KEY_VK_RMENU, OBS_KEY_VK_BROWSER_BACK, OBS_KEY_VK_BROWSER_FORWARD, OBS_KEY_VK_BROWSER_REFRESH, OBS_KEY_VK_BROWSER_STOP, OBS_KEY_VK_BROWSER_SEARCH, OBS_KEY_VK_BROWSER_FAVORITES, OBS_KEY_VK_BROWSER_HOME, OBS_KEY_VK_VOLUME_MUTE, OBS_KEY_VK_VOLUME_DOWN, OBS_KEY_VK_VOLUME_UP, OBS_KEY_VK_MEDIA_NEXT_TRACK, OBS_KEY_VK_MEDIA_PREV_TRACK, OBS_KEY_VK_MEDIA_STOP, OBS_KEY_VK_MEDIA_PLAY_PAUSE, OBS_KEY_VK_LAUNCH_MAIL, OBS_KEY_VK_LAUNCH_MEDIA_SELECT, OBS_KEY_VK_LAUNCH_APP1, OBS_KEY_VK_LAUNCH_APP2, OBS_KEY_0xB8, OBS_KEY_0xB9, OBS_KEY_0xC1, OBS_KEY_0xC2, OBS_KEY_0xC3, OBS_KEY_0xC4, OBS_KEY_0xC5, OBS_KEY_0xC6, OBS_KEY_0xC7, OBS_KEY_0xC8, OBS_KEY_0xC9, OBS_KEY_0xCA, OBS_KEY_0xCB, OBS_KEY_0xCC, OBS_KEY_0xCD, OBS_KEY_0xCE, OBS_KEY_0xCF, OBS_KEY_0xD0, OBS_KEY_0xD1, OBS_KEY_0xD2, OBS_KEY_0xD3, OBS_KEY_0xD4, OBS_KEY_0xD5, OBS_KEY_0xD6, OBS_KEY_0xD7, OBS_KEY_0xD8, OBS_KEY_0xD9, OBS_KEY_0xDA, OBS_KEY_VK_OEM_8, OBS_KEY_0xE0, OBS_KEY_VK_OEM_AX, OBS_KEY_VK_ICO_HELP, OBS_KEY_VK_ICO_00, OBS_KEY_VK_PROCESSKEY, OBS_KEY_VK_ICO_CLEAR, OBS_KEY_VK_PACKET, OBS_KEY_0xE8, OBS_KEY_VK_OEM_RESET, OBS_KEY_VK_OEM_JUMP, OBS_KEY_VK_OEM_PA1, OBS_KEY_VK_OEM_PA2, OBS_KEY_VK_OEM_PA3, OBS_KEY_VK_OEM_WSCTRL, OBS_KEY_VK_OEM_CUSEL, OBS_KEY_VK_OEM_ATTN, OBS_KEY_VK_OEM_FINISH, OBS_KEY_VK_OEM_COPY, OBS_KEY_VK_OEM_AUTO, OBS_KEY_VK_OEM_ENLW, OBS_KEY_VK_ATTN, OBS_KEY_VK_CRSEL, OBS_KEY_VK_EXSEL, OBS_KEY_VK_EREOF, OBS_KEY_VK_PLAY, OBS_KEY_VK_ZOOM, OBS_KEY_VK_NONAME, OBS_KEY_VK_PA1, OBS_KEY_VK_OEM_CLEAR #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member } } ================================================ FILE: obs-websocket-dotnet/Types/OBSScene.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Collections.Generic; namespace OBSWebsocketDotNet.Types { /// /// Describes a scene in OBS, along with its items /// public class ObsScene { /// /// OBS Scene name /// [JsonProperty(PropertyName = "sceneName")] public string Name; /// /// Is group /// [JsonProperty(PropertyName = "isGroup")] public bool IsGroup; /// /// Scene item list /// [JsonProperty(PropertyName = "sources")] public List Items; /// /// Builds the object from the JSON description /// /// JSON scene description as a public ObsScene(JObject data) { JsonSerializerSettings settings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Auto, NullValueHandling = NullValueHandling.Include }; if (data.ContainsKey("currentProgramSceneName")) { var newToken = JToken.FromObject(data["currentProgramSceneName"]); data.Add("sceneName", newToken); } JsonConvert.PopulateObject(data.ToString(), this, settings); } /// /// Default Constructor for deserialization /// public ObsScene() { } } } ================================================ FILE: obs-websocket-dotnet/Types/OBSStats.cs ================================================ using Newtonsoft.Json; namespace OBSWebsocketDotNet.Types { /// /// OBS Stats /// public class ObsStats { /// /// Current framerate. /// [JsonProperty(PropertyName = "activeFps")] public double FPS { set; get; } /// /// Number of frames rendered /// [JsonProperty(PropertyName = "renderTotalFrames")] public long RenderTotalFrames { set; get; } /// /// Number of frames missed due to rendering lag /// [JsonProperty(PropertyName = "renderSkippedFrames")] public long RenderMissedFrames { set; get; } /// /// Number of frames outputted /// [JsonProperty(PropertyName = "outputTotalFrames")] public long OutputTotalFrames { set; get; } /// /// Number of frames skipped due to encoding lag /// [JsonProperty(PropertyName = "outputSkippedFrames")] public long OutputSkippedFrames { set; get; } /// /// Average frame render time (in milliseconds) /// [JsonProperty(PropertyName = "averageFrameRenderTime")] public double AverageFrameTime { set; get; } /// /// Current CPU usage (percentage) /// [JsonProperty(PropertyName = "cpuUsage")] public double CpuUsage { set; get; } /// /// Current RAM usage (in megabytes) /// [JsonProperty(PropertyName = "memoryUsage")] public double MemoryUsage { set; get; } /// /// Free recording disk space (in megabytes) /// [JsonProperty(PropertyName = "availableDiskSpace")] public double FreeDiskSpace { set; get; } /// /// Total number of messages received by obs-websocket from the client /// [JsonProperty(PropertyName = "webSocketSessionIncomingMessages")] public long SessionIncomingMessages { get; set; } /// /// Total number of messages sent by obs-websocket to the client /// [JsonProperty(PropertyName = "webSocketSessionOutgoingMessages")] public long SessionOutgoingMessages { get; set; } } } ================================================ FILE: obs-websocket-dotnet/Types/OBSVersion.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Collections.Generic; namespace OBSWebsocketDotNet.Types { /// /// Version info of the plugin, the API and OBS Studio /// public class ObsVersion { /// /// obs-websocket plugin version /// [JsonProperty(PropertyName = "obsWebSocketVersion")] public string PluginVersion { get; internal set; } /// /// OBS Studio version /// [JsonProperty(PropertyName = "obsVersion")] public string OBSStudioVersion { get; internal set; } /// /// OBSRemote compatible API version.Fixed to 1.1 for retrocompatibility. /// [JsonProperty(PropertyName = "rpcVersion")] public double Version { internal set; get; } /// /// List of available request types, formatted as a comma-separated list string (e.g. : "Method1,Method2,Method3"). /// [JsonProperty(PropertyName = "availableRequests")] public List AvailableRequests { get; internal set; } /// /// Image formats available in `GetSourceScreenshot` and `SaveSourceScreenshot` requests. /// [JsonProperty(PropertyName = "supportedImageFormats")] public List SupportedImageFormats { get; internal set; } /// /// Name of the platform. Usually `windows`, `macos`, or `ubuntu` (linux flavor). Not guaranteed to be any of those /// [JsonProperty(PropertyName = "platform")] public string Platform { get; internal set; } /// /// Description of the platform, like `Windows 10 (10.0)` /// [JsonProperty(PropertyName = "platformDescription")] public string PlatformDescription { get; internal set; } /// /// Builds the object from the JSON response body /// /// JSON response body as a public ObsVersion(JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Empty constructor for jsonconvert /// public ObsVersion() { } } } ================================================ FILE: obs-websocket-dotnet/Types/OBSVideoSettings.cs ================================================ using Newtonsoft.Json; namespace OBSWebsocketDotNet.Types { /// /// Basic OBS video information /// public class ObsVideoSettings { /// /// Numerator of the fractional FPS value /// [JsonProperty(PropertyName = "fpsNumerator")] public double FpsNumerator { set; get; } /// /// Denominator of the fractional FPS value /// [JsonProperty(PropertyName = "fpsDenominator")] public double FpsDenominator { set; get; } /// /// Base (canvas) width /// [JsonProperty(PropertyName = "baseWidth")] public int BaseWidth { set; get; } /// /// Base (canvas) height /// [JsonProperty(PropertyName = "baseHeight")] public int BaseHeight { set; get; } /// /// Width of the output resolution in pixels /// [JsonProperty(PropertyName = "outputWidth")] public int OutputWidth { set; get; } /// /// Height of the output resolution in pixels /// [JsonProperty(PropertyName = "outputHeight")] public int OutputHeight { set; get; } } } ================================================ FILE: obs-websocket-dotnet/Types/OutputState.cs ================================================ namespace OBSWebsocketDotNet.Types { /// /// Describes the state of an output (streaming or recording) /// public enum OutputState { /// /// The output is initializing and doesn't produce frames yet /// OBS_WEBSOCKET_OUTPUT_STARTING, /// /// The output is running and produces frames /// OBS_WEBSOCKET_OUTPUT_STARTED, /// /// The output is stopping and sends the last remaining frames in its buffer /// OBS_WEBSOCKET_OUTPUT_STOPPING, /// /// The output is completely stopped /// OBS_WEBSOCKET_OUTPUT_STOPPED, /// /// The output is paused (usually recording output) /// OBS_WEBSOCKET_OUTPUT_PAUSED, /// /// The output is resumed (i.e. no longer paused) - usually recording output /// OBS_WEBSOCKET_OUTPUT_RESUMED } } ================================================ FILE: obs-websocket-dotnet/Types/OutputStateChanged.cs ================================================ using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Data when Stream/Recording/Instant_Replay change states /// public class OutputStateChanged { private OutputState? state; /// /// Is output currently active (streaming/recording) /// [JsonProperty(PropertyName = "outputActive")] public bool IsActive { set; get; } /// /// Output state as string /// [JsonProperty(PropertyName = "outputState")] public string StateStr { set; get; } /// /// OutputState enum of current state /// public OutputState State { get { if (state.HasValue) { return state.Value; } if (!Enum.TryParse(StateStr, ignoreCase: true, out OutputState stateTmp)) { throw new ArgumentOutOfRangeException($"Couldn't parse '{StateStr}' as {nameof(OutputState)}"); } state = stateTmp; return state.Value; } } /// /// Constructor /// /// public OutputStateChanged(JObject body) { JsonConvert.PopulateObject(body.ToString(), this); } /// /// Default Constructor for deserialization /// public OutputStateChanged() { } } } ================================================ FILE: obs-websocket-dotnet/Types/OutputStatus.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Status of streaming output /// public class OutputStatus { /// /// True if streaming is started and running, false otherwise /// [JsonProperty(PropertyName = "outputActive")] public readonly bool IsActive; /// /// Whether the output is currently reconnectins /// [JsonProperty(PropertyName = "outputReconnecting")] public bool IsReconnecting { get; set; } /// /// Current formatted timecode string for the output /// [JsonProperty(PropertyName = "outputTimecode")] public string TimeCode { get; set; } /// /// Current duration in milliseconds for the output /// [JsonProperty(PropertyName = "outputDuration")] public long Duration { get; set; } /// /// Congestion of the output /// [JsonProperty(PropertyName = "outputCongestion")] public double Congestion { get; set; } /// /// Nubmer of bytes sent by the output /// [JsonProperty(PropertyName = "outputBytes")] public long BytesSent { get; set; } /// /// Number of frames skipped by the output's process /// [JsonProperty(PropertyName = "outputSkippedFrames")] public long SkippedFrames { get; set; } /// /// Total number of frames delivered by the output's process /// [JsonProperty(PropertyName = "outputTotalFrames")] public long TotalFrames { get; set; } /// /// Builds the object from the JSON response body /// /// JSON response body as a public OutputStatus(JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Default Constructor for deserialization /// public OutputStatus() { } } } ================================================ FILE: obs-websocket-dotnet/Types/RecordStateChanged.cs ================================================ using Newtonsoft.Json.Linq; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Text; namespace OBSWebsocketDotNet.Types { /// /// Data when Recording change states /// public class RecordStateChanged : OutputStateChanged { /// /// File name for the saved recording, if record stopped. null otherwise /// [JsonProperty(PropertyName = "outputPath")] public string OutputPath { set; get; } /// /// Constructor /// /// public RecordStateChanged(JObject body) :base(body) { JsonConvert.PopulateObject(body.ToString(), this); } /// /// Default Constructor for deserialization /// public RecordStateChanged() { } } } ================================================ FILE: obs-websocket-dotnet/Types/RecordingStatus.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// GetRecordingStatus response /// public class RecordingStatus { /// /// Current recording status /// [JsonProperty(PropertyName = "outputActive")] public bool IsRecording { set; get; } /// /// Whether the recording is paused or not /// [JsonProperty(PropertyName = "outputPaused")] public bool IsRecordingPaused { set; get; } /// /// Current formatted timecode string for the output /// [JsonProperty(PropertyName = "outputTimecode")] public string RecordTimecode { set; get; } /// /// Current duration in milliseconds for the output /// [JsonProperty(PropertyName = "outputDuration")] public long RecordingDuration { set; get; } /// /// Number of bytes sent by the output /// [JsonProperty(PropertyName = "outputBytes")] public long RecordingBytes { set; get; } /// /// Builds the object from the JSON response body /// /// JSON response body as a public RecordingStatus(JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Default Constructor for deserialization /// public RecordingStatus() { } } } ================================================ FILE: obs-websocket-dotnet/Types/SceneBasicInfo.cs ================================================ using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Text; namespace OBSWebsocketDotNet.Types { /// /// Response from /// public class SceneBasicInfo { /// /// Name of scene /// [JsonProperty(PropertyName = "sceneName")] public string Name { set; get; } /// /// Index of scene /// [JsonProperty(PropertyName = "sceneIndex")] public string Index { set; get; } } } ================================================ FILE: obs-websocket-dotnet/Types/SceneItemBoundsType.cs ================================================ namespace OBSWebsocketDotNet.Types { /// /// Types of bounding boxes for scene items /// public enum SceneItemBoundsType { /// /// Stretch /// OBS_BOUNDS_STRETCH, /// /// Inner scale /// OBS_BOUNDS_SCALE_INNER, /// /// Outer scale /// OBS_BOUNDS_SCALE_OUTER, /// /// Scale to width /// OBS_BOUNDS_SCALE_TO_WIDTH, /// /// Scale to height /// OBS_BOUNDS_SCALE_TO_HEIGHT, /// /// Max only /// OBS_BOUNDS_MAX_ONLY, /// /// No bounds /// OBS_BOUNDS_NONE } } ================================================ FILE: obs-websocket-dotnet/Types/SceneItemDetails.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Text; namespace OBSWebsocketDotNet.Types { /// /// Meta data regarding a Scene item /// public class SceneItemDetails { /// /// Unique item id of the source item /// [JsonProperty(PropertyName = "sceneItemId")] public int ItemId { set; get; } /// /// Kind of source (Example: vlc_source or image_source) /// [JsonProperty(PropertyName = "inputKind")] public string SourceKind { set; get; } /// /// Name of the scene item's source /// [JsonProperty(PropertyName = "sourceName")] public string SourceName { set; get; } /// /// Type of the scene item's source. /// [JsonProperty(PropertyName = "sourceType")] public SceneItemSourceType SourceType { set; get; } /// /// Builds the object from the JSON data /// /// JSON item description as a public SceneItemDetails(JObject data) { if (data != null) { JsonConvert.PopulateObject(data.ToString(), this); } } /// /// Default Constructor for deserialization /// public SceneItemDetails() { } } } ================================================ FILE: obs-websocket-dotnet/Types/SceneItemSourceType.cs ================================================ namespace OBSWebsocketDotNet.Types { /// /// Type of scene item's source /// public enum SceneItemSourceType { /// /// Input /// OBS_SOURCE_TYPE_INPUT, /// /// Filter /// OBS_SOURCE_TYPE_FILTER, /// /// Transition /// OBS_SOURCE_TYPE_TRANSITION, /// /// Scene /// OBS_SOURCE_TYPE_SCENE } } ================================================ FILE: obs-websocket-dotnet/Types/SceneItemTransformInfo.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Item transformation information /// public class SceneItemTransformInfo { /// /// Alignment of the item /// [JsonProperty(PropertyName = "alignment")] public int Alignnment { set; get; } /// /// The point on the scene item that the item is manipulated from /// [JsonProperty(PropertyName = "boundsAlignment")] public int BoundsAlignnment { set; get; } /// /// Height of the bounding box /// [JsonProperty(PropertyName = "boundsHeight")] public double BoundsHeight { set; get; } /// /// Width of the bounding box /// [JsonProperty(PropertyName = "boundsWidth")] public double BoundsWidth { set; get; } /// /// Type of bounding box /// [JsonProperty(PropertyName = "boundsType")] [JsonConverter(typeof(StringEnumConverter))] public SceneItemBoundsType BoundsType { set; get; } /// /// Bottom crop (in pixels) /// [JsonProperty(PropertyName = "cropBottom")] public int CropBottom; /// /// Left crop (in pixels) /// [JsonProperty(PropertyName = "cropLeft")] public int CropLeft; /// /// Right crop (in pixels) /// [JsonProperty(PropertyName = "cropRight")] public int CropRight; /// /// Top crop (in pixels) /// [JsonProperty(PropertyName = "cropTop")] public int CropTop; /// /// The clockwise rotation of the scene item in degrees around the point of alignment. /// [JsonProperty(PropertyName = "rotation")] public double Rotation { set; get; } /// /// The x-scale factor of the scene item /// [JsonProperty(PropertyName = "scaleX")] public double ScaleX { get; set; } /// /// The y-scale factor of the scene item /// [JsonProperty(PropertyName = "scaleY")] public double ScaleY { get; set; } /// /// Base height (without scaling) of the source /// [JsonProperty(PropertyName = "sourceHeight")] public double SourceHeight { set; get; } /// /// Base width (without scaling) of the source /// [JsonProperty(PropertyName = "sourceWidth")] public double SourceWidth { set; get; } /// /// Scene item height (base source height multiplied by the vertical scaling factor) /// [JsonProperty(PropertyName = "height")] public double Height { set; get; } /// /// Scene item width (base source width multiplied by the horizontal scaling factor) /// [JsonProperty(PropertyName = "width")] public double Width { set; get; } /// /// The x position of the scene item from the left /// [JsonProperty(PropertyName = "positionX")] public double X { set; get; } /// /// The y position of the scene item from the top /// [JsonProperty(PropertyName = "positionY")] public double Y { set; get; } /// /// Initialize the scene item transform /// /// public SceneItemTransformInfo(JObject body) { JsonConvert.PopulateObject(body.ToString(), this); } /// /// Default Constructor for deserialization /// public SceneItemTransformInfo() { } } } ================================================ FILE: obs-websocket-dotnet/Types/SourceActiveInfo.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Gets the Active and Showing state of a video source /// public class SourceActiveInfo { /// /// Whether the source is showing in Program /// [JsonProperty(PropertyName = "videaActive")] public bool VideoActive { get; set; } /// /// Whether the source is showing in the UI (Preview, Projector, Properties) /// [JsonProperty(PropertyName = "videoShowing")] public bool VideoShowing { get; set; } /// /// Auto populate constructor /// /// public SourceActiveInfo(JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Default Constructor /// public SourceActiveInfo() { } } } ================================================ FILE: obs-websocket-dotnet/Types/SourceTracks.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Tracks status for a source item /// public class SourceTracks { /// /// Is the track active /// [JsonProperty(PropertyName = "1")] public bool IsTrack1Active { set; get; } /// /// Is the track active /// [JsonProperty(PropertyName = "2")] public bool IsTrack2Active { set; get; } /// /// Is the track active /// [JsonProperty(PropertyName = "3")] public bool IsTrack3Active { set; get; } /// /// Is the track active /// [JsonProperty(PropertyName = "4")] public bool IsTrack4Active { set; get; } /// /// Is the track active /// [JsonProperty(PropertyName = "5")] public bool IsTrack5Active { set; get; } /// /// Is the track active /// [JsonProperty(PropertyName = "6")] public bool IsTrack6Active { set; get; } /// /// Builds the object from the JSON data /// /// JSON item description as a public SourceTracks(JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Default Constructor for deserialization /// public SourceTracks() { } } } ================================================ FILE: obs-websocket-dotnet/Types/StreamingService.cs ================================================ using Newtonsoft.Json; namespace OBSWebsocketDotNet.Types { /// /// Streaming settings /// public class StreamingService { /// /// Type of streaming service /// [JsonProperty(PropertyName = "streamServiceType")] public string Type { set; get; } /// /// Streaming service settings (JSON data) /// [JsonProperty(PropertyName = "streamServiceSettings")] public StreamingServiceSettings Settings { set; get; } } } ================================================ FILE: obs-websocket-dotnet/Types/StreamingServiceSettings.cs ================================================ using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Streaming server settings /// public class StreamingServiceSettings { /// /// The publish URL /// [JsonProperty(PropertyName = "server")] public string Server { set; get; } /// /// The publish key of the stream /// [JsonProperty(PropertyName = "key")] public string Key { set; get; } /// /// Indicates whether authentication should be used when connecting to the streaming server /// [JsonProperty(PropertyName = "use_auth")] public bool UseAuth { set; get; } /// /// The username to use when accessing the streaming server. Only present if use-auth is true /// [JsonProperty(PropertyName = "username")] public string Username { set; get; } /// /// The password to use when accessing the streaming server. Only present if use-auth is true /// [JsonProperty(PropertyName = "password")] public string Password { set; get; } /// /// The service being used to stream /// [JsonProperty(PropertyName = "service")] public string Service { get; set; } /// /// The protocol to use for the stream /// [JsonProperty(PropertyName = "protocol")] public string Protocol { get; set; } /// /// Other values not covered by the class /// [JsonExtensionData] public Dictionary OtherValues { get; set; } } } ================================================ FILE: obs-websocket-dotnet/Types/TransitionOverrideInfo.cs ================================================ using Newtonsoft.Json; namespace OBSWebsocketDotNet.Types { /// /// Scene transition override settings /// public class TransitionOverrideInfo { /// /// Name of the current overriding transition. Empty string if no override is set. /// [JsonProperty(PropertyName = "transitionName")] public string Name { internal set; get; } /// /// Transition duration in milliseconds. -1 if no override is set. /// [JsonProperty(PropertyName = "transitionDuration")] public int Duration { internal set; get; } } } ================================================ FILE: obs-websocket-dotnet/Types/TransitionSettings.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Current transition settings /// public class TransitionSettings { /// /// Transition name /// [JsonProperty(PropertyName = "transitionName")] public string Name { internal set; get; } /// /// Transition duration in milliseconds /// [JsonProperty(PropertyName = "transitionDuration")] public int? Duration { internal set; get; } /// /// Kind of the transition /// [JsonProperty(PropertyName = "transitionKind")] public string Kind { internal set; get; } /// /// Whether the transition uses a fixed (unconfigurable) duration /// [JsonProperty(PropertyName = "transitionFixed")] public bool IsFixed { internal set; get; } /// /// Whether the transition supports being configured /// [JsonProperty(PropertyName = "transitionConfigurable")] public bool IsConfigurable { internal set; get; } /// /// Object of settings for the transition. 'null' if transition is not configurable /// [JsonProperty(PropertyName = "transitionSettings")] public JObject Settings { get; set; } /// /// Builds the object from the JSON response body /// /// JSON response body as a public TransitionSettings(JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Default Constructor for deserialization /// public TransitionSettings() { } } } ================================================ FILE: obs-websocket-dotnet/Types/VirtualCamStatus.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// VirtualCam Status /// public class VirtualCamStatus { /// /// Whether the output is active /// [JsonProperty(PropertyName = "outputActive")] public bool IsActive { get; set; } /// /// Builds the object from the JSON response body /// /// JSON response body as a public VirtualCamStatus(JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Constructor for jsonconverter /// public VirtualCamStatus() { } } } ================================================ FILE: obs-websocket-dotnet/Types/VolumeInfo.cs ================================================ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace OBSWebsocketDotNet.Types { /// /// Volume settings of an OBS source /// public class VolumeInfo { /// /// Source volume in linear scale (0.0 to 1.0) /// [JsonProperty(PropertyName = "inputVolumeMul")] public float VolumeMul { internal set; get; } /// /// Volume setting in dB /// [JsonProperty(PropertyName = "inputVolumeDb")] public float VolumeDb { internal set; get; } /// /// Builds the object from the JSON response body /// /// JSON response body as a public VolumeInfo(JObject data) { JsonConvert.PopulateObject(data.ToString(), this); } /// /// Default Constructor for deserialization /// public VolumeInfo() { } } } ================================================ FILE: obs-websocket-dotnet/obs-websocket-dotnet.csproj ================================================ netstandard2.1 obs-websocket-dotnet OBSWebsocketDotNet Copyright © BarRaider 2025 8 5.0.1 BarRaider LICENSE https://github.com/BarRaider/obs-websocket-dotnet https://github.com/BarRaider/obs-websocket-dotnet Official obs-websocket .NET library. Written in C#. Supports .NET Standard OBS obs-websocket websocket official obs-websocket-dotnet obs.websocket.net obs-websocket-net true What's new in v5.0.1 * Fixes for deserialization issues in MediaInputStatus * Allow OBSVideoSettings to be updated via the API * New ILogger support instead of writing to console * New UnsupportedEvent event obs-websocket-dotnet.xml True ================================================ FILE: obs-websocket-dotnet/obs-websocket-dotnet.xml ================================================ obs-websocket-dotnet Data required by authentication Authentication challenge Password salt Builds the object from JSON response body JSON response body as a Default Constructor for deserialization Close/Error codes sent by OBS Websocket when closing the connection For internal use only to tell the request handler not to perform any close action. Unknown reason, should never be used. The server was unable to decode the incoming websocket message. A data field is required but missing from the payload. A data field's value type is invalid. A data field's value is invalid. The specified op was invalid or missing. The client sent a websocket message without first sending Identify message. The client sent an Identify message while already identified. The authentication attempt (via Identify) failed. The server detected the usage of an old version of the obs-websocket RPC protocol. The websocket session has been invalidated by the obs-websocket server. A requested feature is not supported due to hardware/software limitations. Disconnection information received from the OBS Websocket server Close/Error codes sent by OBS Websocket when closing the connection String reason of disconnect Websocket Client internal information Constructor Close/Error codes sent by OBS Websocket when closing the connection String reason of disconnect Websocket Client internal information Message received from the server Server Message's operation code Server Data Instance of a connection with an obs-websocket server The current program scene has changed. The list of scenes has changed. TODO: Make OBS fire this event when scenes are reordered. Triggered when the scene item list of the specified scene is reordered Triggered when a new item is added to the item list of the specified scene Triggered when an item is removed from the item list of the specified scene Triggered when the visibility of a scene item changes Triggered when the lock status of a scene item changes Triggered when switching to another scene collection Triggered when a scene collection is created, deleted or renamed Triggered when switching to another transition Triggered when the current transition duration is changed Triggered when a transition between two scenes starts. Followed by Triggered when a transition (other than "cut") has ended. Please note that the from-scene field is not available in TransitionEnd Triggered when a stinger transition has finished playing its video Triggered when switching to another profile Triggered when a profile is created, imported, removed or renamed Triggered when the streaming output state changes Triggered when the recording output state changes Triggered when state of the replay buffer changes Triggered when the preview scene selection changes (Studio Mode only) Triggered when Studio Mode is turned on or off Triggered when OBS exits Triggered when connected successfully to an obs-websocket server Triggered when disconnected from an obs-websocket server A scene item is selected in the UI A scene item transform has changed The audio sync offset of an input has changed A filter was added to a source A filter was removed from a source Filters in a source have been reordered Triggered when the visibility of a filter has changed A source has been muted or unmuted The volume of a source has changed A custom broadcast message was received These events are emitted by the OBS sources themselves. For example when the media file ends. The behavior depends on the type of media source being used. These events are emitted by the OBS sources themselves. For example when the media file starts playing. The behavior depends on the type of media source being used. This event is only emitted when something actively controls the media/VLC source. In other words, the source will never emit this on its own naturally. The virtual cam state has changed. The current scene collection has begun changing. The current profile has begun changing. The name of a source filter has changed. An input has been created. An input has been removed. The name of an input has changed. An input's active state has changed. When an input is active, it means it's being shown by the program feed. An input's show state has changed. When an input is showing, it means it's being shown by the preview or a dialog. The audio balance value of an input has changed. The audio tracks of an input have changed. The monitor type of an input has changed. Available types are: - `OBS_MONITORING_TYPE_NONE` - `OBS_MONITORING_TYPE_MONITOR_ONLY` - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` A high-volume event providing volume levels of all active inputs every 50 milliseconds. The replay buffer has been saved. A new scene has been created. A scene has been removed. The name of a scene has changed. An unsupported event has been received. Update message handler Value of "event-type" in the JSON body full JSON message body WebSocket request timeout, represented as a TimeSpan object Current connection state Gets or sets the logger for this instance Constructor Connect this instance to the specified URL, and authenticate (if needed) with the specified password. NOTE: Please subscribe to the Connected/Disconnected events (or atleast check the IsConnected property) to determine when the connection is actually fully established Server URL in standard URL format. Server password Connect this instance to the specified URL, and authenticate (if needed) with the specified password. NOTE: Please subscribe to the Connected/Disconnected events (or atleast check the IsConnected property) to determine when the connection is actually fully established Server URL in standard URL format. Server password Disconnect this instance from the server Sends a message to the websocket API with the specified request type and optional parameters obs-websocket request type, must be one specified in the protocol specification additional JSON fields if required by the request type The server's JSON response as a JObject Internal version which allows to set the opcode Sends a message to the websocket API with the specified request type and optional parameters Type/OpCode for this messaage obs-websocket request type, must be one specified in the protocol specification additional JSON fields if required by the request type Should wait for reply vs "fire and forget" The server's JSON response as a JObject Request authentication data. You don't have to call this manually. Authentication data in an object Authenticates to the Websocket server using the challenge and salt given in the passed object User password Authentication data true if authentication succeeds, false otherwise Encode a Base64-encoded SHA-256 hash source string Generate a message ID (optional) message ID length A random string of alphanumerical characters Get basic OBS video information Saves a screenshot of a source to the filesystem. The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. **Compatible with inputs and scenes.** Name of the source to take a screenshot of Image compression format to use. Use `GetVersion` to get compatible image formats Path to save the screenshot file to. Eg. `C:\\Users\\user\\Desktop\\screenshot.png` Width to scale the screenshot to Height to scale the screenshot to Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use \"default\" (whatever that means, idk) Base64-encoded screenshot string Saves a screenshot of a source to the filesystem. The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. **Compatible with inputs and scenes.** Name of the source to take a screenshot of Image compression format to use. Use `GetVersion` to get compatible image formats Path to save the screenshot file to. Eg. `C:\\Users\\user\\Desktop\\screenshot.png` Base64-encoded screenshot string Executes hotkey routine, identified by hotkey unique name Unique name of the hotkey, as defined when registering the hotkey (e.g. "ReplayBuffer.Save") Triggers a hotkey using a sequence of keys. Main key identifier (e.g. OBS_KEY_A for key "A"). Available identifiers are here: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-hotkeys.h Optional key modifiers object. You can combine multiple key operators. e.g. KeyModifier.Shift | KeyModifier.Control Get the name of the currently active scene. Name of the current scene Set the current scene to the specified one The desired scene name Get OBS stats (almost the same info as provided in OBS' stats window) List every available scene A of objects describing each scene Get a list of scenes in the currently active profile Get the specified scene's transition override info Name of the scene to return the override info TransitionOverrideInfo Set specific transition override for a scene Name of the scene to set the transition override Name of the transition to use Duration in milliseconds of the transition if transition is not fixed. Defaults to the current duration specified in the UI if there is no current override and this value is not given If your code needs to perform multiple successive T-Bar moves (e.g. : in an animation, or in response to a user moving a T-Bar control in your User Interface), set release to false and call ReleaseTBar later once the animation/interaction is over. T-Bar position. This value must be between 0.0 and 1.0. Whether or not the T-Bar gets released automatically after setting its new position (like a user releasing their mouse button after moving the T-Bar). Call ReleaseTBar manually if you set release to false. Defaults to true. Apply settings to a source filter Source with filter Filter name JObject with filter settings Apply over existing settings? Apply settings to a source filter Source with filter Filter name Filter settings Apply over existing settings? Modify the Source Filter's visibility Source name Source filter name New filter state Return a list of all filters on a source Source name Return a list of settings for a specific filter Source name Filter name Remove the filter from a source Name of the source the filter is on Name of the filter to remove Add a filter to a source Name of the source for the filter Name of the filter Type of filter JObject holding filter settings object Add a filter to a source Name of the source for the filter Name of the filter Type of filter Filter settings object Toggles the status of the stream output. New state of the stream output Toggles the status of the record output. Gets the status of the stream output An object describing the current outputs states Get the current transition name and duration An object with the current transition name and duration Set the current transition to the specified one Desired transition name Change the transition's duration Desired transition duration (in milliseconds) Change the current settings of a transition Transition settings (they can be partial) Whether to overlay over the current settins or replace them Updated transition settings Change the volume of the specified source Name of the source which volume will be changed Desired volume. Must be between `0.0` and `1.0` for amplitude/mul (useDecibel is false), and under 0.0 for dB (useDecibel is true). Note: OBS will interpret dB values under -100.0 as Inf. Interperet `volume` data as decibels instead of amplitude/mul. Get the volume of the specified source Volume is between `0.0` and `1.0` if using amplitude/mul (useDecibel is false), under `0.0` if using dB (useDecibel is true). Source name An Object containing the volume and mute state of the specified source. Gets the audio mute state of an input. Name of input to get the mute state of Whether the input is muted Set the mute state of the specified source Name of the source which mute state will be changed Desired mute state Toggle the mute state of the specified source Name of the source which mute state will be toggled Sets the transform and crop info of a scene item Name of the scene that has the SceneItem Id of the Scene Item JObject holding transform settings Sets the transform and crop info of a scene item Name of the scene that has the SceneItem Id of the Scene Item Transform settings Set the current scene collection to the specified one Desired scene collection name Get the name of the current scene collection Name of the current scene collection List all scene collections A of the names of all scene collections Set the current profile to the specified one Name of the desired profile List all profiles A of the names of all profiles Start streaming. Will trigger an error if streaming is already active Stop streaming. Will trigger an error if streaming is not active. Start recording. Will trigger an error if recording is already active. Stop recording. Will trigger an error if recording is not active. File name for the saved recording Pause the current recording. Returns an error if recording is not active or already paused. Resume/unpause the current recording (if paused). Returns an error if recording is not active or not paused. Get the path of the current recording folder Current recording folder path Get current recording status. Get the status of the OBS replay buffer. Current recording status. true when active Get duration of the currently selected transition (if supported) Current transition duration (in milliseconds) Get status of Studio Mode Studio Mode status (on/off) Enables or disables studio mode Get the name of the currently selected preview scene. Note: Triggers an error if Studio Mode is disabled Preview scene name Change the currently active preview/studio scene to the one specified. Triggers an error if Studio Mode is disabled Preview scene name Change the currently active preview/studio scene to the one specified. Triggers an error if Studio Mode is disabled. Preview scene object Triggers the current scene transition. Same functionality as the `Transition` button in Studio Mode Toggles the state of the replay buffer output. Start recording into the Replay Buffer. Triggers an error if the Replay Buffer is already active, or if the "Save Replay Buffer" hotkey is not set in OBS' settings Stop recording into the Replay Buffer. Triggers an error if the Replay Buffer is not active. Save and flush the contents of the Replay Buffer to disk. Basically the same as triggering the "Save Replay Buffer" hotkey in OBS. Triggers an error if Replay Buffer is not active. Set the audio sync offset of the specified source Source name Audio offset (in nanoseconds) for the specified source Get the audio sync offset of the specified source Source name Audio offset (in nanoseconds) of the specified source Removes a scene item from a scene. Scenes only. Scene item id Scene name from which to delete item Sends CEA-608 caption text over the stream output. As of OBS Studio 23.1, captions are not yet available on Linux. Captions text Duplicates a scene item Name of the scene that has the SceneItem Id of the Scene Item Name of scene to add the new duplicated Scene Item. If not specified will assume sceneName Gets the names of all special inputs. Dictionary of special inputs. Sets the current stream service settings (stream destination). Note: Simple RTMP settings can be set with type `rtmp_custom` and the settings fields `server` and `key`. Stream Service Type Name and Settings objects Gets the current stream service settings (stream destination). Stream service type and settings objects Gets the audio monitor type of an input. The available audio monitor types are: - `OBS_MONITORING_TYPE_NONE` - `OBS_MONITORING_TYPE_MONITOR_ONLY` - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` Source name The monitor type in use Sets the audio monitor type of an input. Name of the input to set the audio monitor type of Audio monitor type. See `GetInputAudioMonitorType for possible types. Broadcasts a `CustomEvent` to all WebSocket clients. Receivers are clients which are identified and subscribed. Data payload to emit to all receivers Sets the cursor position of a media input. This request does not perform bounds checking of the cursor position. Name of the media input New cursor position to set (milliseconds). Offsets the current cursor position of a media input by the specified value. This request does not perform bounds checking of the cursor position. Name of the media input Value to offset the current cursor position by (milliseconds +/-) Creates a new input, adding it as a scene item to the specified scene. Name of the scene to add the input to as a scene item Name of the new input to created The kind of input to be created Jobject holding the settings object to initialize the input with Whether to set the created scene item to enabled or disabled ID of the SceneItem in the scene. Gets the default settings for an input kind. Input kind to get the default settings for Object of default settings for the input kind Gets a list of all scene items in a scene. Scenes only Name of the scene to get the items of Array of scene items in the scene Creates a new scene item using a source. Scenes only Name of the scene to create the new item in Name of the source to add to the scene Enable state to apply to the scene item on creation Numeric ID of the scene item Creates a new scene in OBS. Name for the new scene Gets the enable state of all audio tracks of an input. Name of the input Object of audio tracks and associated enable states Sets the enable state of audio tracks of an input. Name of the input JObject holding track settings to apply Sets the enable state of audio tracks of an input. Name of the input Track settings to apply Gets the active and show state of a source. **Compatible with inputs and scenes.** Name of the source to get the active state of Whether the source is showing in Program Gets the status of the virtualcam output. An object describing the current virtual camera state Starts the virtualcam output. Stops the virtualcam output. Toggles the state of the virtualcam output. Whether the output is active Gets the value of a \"slot\" from the selected persistent data realm. The data realm to select. `OBS_WEBSOCKET_DATA_REALM_GLOBAL` or `OBS_WEBSOCKET_DATA_REALM_PROFILE` The name of the slot to retrieve data from Value associated with the slot. `null` if not set Sets the value of a \"slot\" from the selected persistent data realm. The data realm to select. `OBS_WEBSOCKET_DATA_REALM_GLOBAL` or `OBS_WEBSOCKET_DATA_REALM_PROFILE` The name of the slot to retrieve data from The value to apply to the slot Creates a new scene collection, switching to it in the process.\n\nNote: This will block until the collection has finished changing. Name for the new scene collection Creates a new profile, switching to it in the process Name for the new profile Removes a profile. If the current profile is chosen, it will change to a different profile first. Name of the profile to remove Gets a parameter from the current profile's configuration. Category of the parameter to get Name of the parameter to get Sets the value of a parameter in the current profile's configuration. Category of the parameter to set Name of the parameter to set Value of the parameter to set. Use `null` to delete Sets the current video settings. Note: Fields must be specified in pairs. For example, you cannot set only `baseWidth` without needing to specify `baseHeight`. Object containing video settings Gets the default settings for a filter kind. Filter kind to get the default settings for Object of default settings for the filter kind Sets the name of a source filter (rename). Name of the source the filter is on Current name of the filter New name for the filter Sets the index position of a filter on a source. Name of the source the filter is on Name of the filter New index position of the filter Gets data about the current plugin and RPC version. Version info in an object Call a request registered to a vendor. A vendor is a unique name registered by a third-party plugin or script, which allows for custom requests and events to be added to obs-websocket. If a plugin or script implements vendor requests or events, documentation is expected to be provided with them. Name of the vendor to use The request type to call Object containing appropriate request data Object containing appropriate response data. {} if request does not provide any response data Gets an array of all hotkey names in OBS Array of hotkey names Sleeps for a time duration or number of frames. Only available in request batches with types `SERIAL_REALTIME` or `SERIAL_FRAME`. Number of milliseconds to sleep for (if `SERIAL_REALTIME` mode) Number of frames to sleep for (if `SERIAL_FRAME` mode) Gets an array of all inputs in OBS. Restrict the array to only inputs of the specified kind List of Inputs in OBS Gets an array of all available input kinds in OBS. True == Return all kinds as unversioned, False == Return with version suffixes (if available) Array of input kinds Removes an existing input. Note: Will immediately remove all associated scene items. Name of the input to remove Sets the name of an input (rename). Current input name New name for the input Gets the settings of an input. Note: Does not include defaults. To create the entire settings object, overlay `inputSettings` over the `defaultInputSettings` provided by `GetInputDefaultSettings`. Name of the input to get the settings of New populated InputSettings object Sets the settings of an input. Object of settings to apply True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. Sets the settings of an input. Name of the input to set the settings of Object of settings to apply True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. Gets the audio balance of an input. Name of the input to get the audio balance of Audio balance value from 0.0-1.0 Sets the audio balance of an input. Name of the input to set the audio balance of New audio balance value Gets the items of a list property from an input's properties. Note: Use this in cases where an input provides a dynamic, selectable list of items. For example, display capture, where it provides a list of available displays. Name of the input Name of the list property to get the items of Array of items in the list property Presses a button in the properties of an input. Note: Use this in cases where there is a button in the properties of an input that cannot be accessed in any other way. For example, browser sources, where there is a refresh button. Name of the input Name of the button property to press Gets the status of a media input.\n\nMedia States: - `OBS_MEDIA_STATE_NONE` - `OBS_MEDIA_STATE_PLAYING` - `OBS_MEDIA_STATE_OPENING` - `OBS_MEDIA_STATE_BUFFERING` - `OBS_MEDIA_STATE_PAUSED` - `OBS_MEDIA_STATE_STOPPED` - `OBS_MEDIA_STATE_ENDED` - `OBS_MEDIA_STATE_ERROR` Name of the media input Object containing string mediaState, int mediaDuration, int mediaCursor properties Triggers an action on a media input. Name of the media input Identifier of the `ObsMediaInputAction` enum Gets the filename of the last replay buffer save file. File path of last replay Toggles pause on the record output. Currently BROKEN in obs-websocket/obs-studio Basically GetSceneItemList, but for groups. Using groups at all in OBS is discouraged, as they are very broken under the hood. Groups only Name of the group to get the items of Array of scene items in the group Searches a scene for a source, and returns its id.\n\nScenes and Groups Name of the scene or group to search in Name of the source to find Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item Numeric ID of the scene item Gets the transform and crop info of a scene item. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Object containing scene item transform info Gets the JObject of transform settings for a scene item. Use this one you don't want it populated with default values. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Object containing scene item transform info Gets the enable state of a scene item. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Whether the scene item is enabled. `true` for enabled, `false` for disabled Gets the enable state of a scene item. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item New enable state of the scene item Gets the lock state of a scene item. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Whether the scene item is locked. `true` for locked, `false` for unlocked Sets the lock state of a scene item. Scenes and Group Name of the scene the item is in Numeric ID of the scene item New lock state of the scene item Gets the index position of a scene item in a scene. An index of 0 is at the bottom of the source list in the UI. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Index position of the scene item Sets the index position of a scene item in a scene. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item New index position of the scene item Gets the blend mode of a scene item. Blend modes: - `OBS_BLEND_NORMAL` - `OBS_BLEND_ADDITIVE` - `OBS_BLEND_SUBTRACT` - `OBS_BLEND_SCREEN` - `OBS_BLEND_MULTIPLY` - `OBS_BLEND_LIGHTEN` - `OBS_BLEND_DARKEN` Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Current blend mode Sets the blend mode of a scene item. Scenes and Groups Gets an array of all groups in OBS. Groups in OBS are actually scenes, but renamed and modified. In obs-websocket, we treat them as scenes where we can. Array of group names Removes a scene from OBS. Name of the scene to remove Sets the name of a scene (rename). Name of the scene to be renamed New name for the scene Gets a Base64-encoded screenshot of a source. The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. **Compatible with inputs and scenes.** Name of the source to take a screenshot of Image compression format to use. Use `GetVersion` to get compatible image formats Width to scale the screenshot to Height to scale the screenshot to Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use \"default\" (whatever that means, idk) Base64-encoded screenshot Gets an array of all available transition kinds. Similar to `GetInputKindList` Array of transition kinds Gets the cursor position of the current scene transition. Note: `transitionCursor` will return 1.0 when the transition is inactive. Cursor position, between 0.0 and 1.0 Opens the properties dialog of an input. Name of the input to open the dialog of Opens the filters dialog of an input. Name of the input to open the dialog of Opens the interact dialog of an input. Name of the input to open the dialog of Gets a list of connected monitors and information about them. a list of detected monitors with some information Opens a projector for a source. Note: This request serves to provide feature parity with 4.x. It is very likely to be changed/deprecated in a future release. Name of the source to open a projector for Size/Position data for a windowed projector, in Qt Base64 encoded format. Mutually exclusive with monitorIndex Monitor index, use GetMonitorList to obtain index. -1 to open in windowed mode Opens a projector for a specific output video mix. Note: This request serves to provide feature parity with 4.x. It is very likely to be changed/deprecated in a future release. Mix types: OBS_WEBSOCKET_VIDEO_MIX_TYPE_PREVIEW, OBS_WEBSOCKET_VIDEO_MIX_TYPE_PROGRAM, OBS_WEBSOCKET_VIDEO_MIX_TYPE_MULTIVIEW Size/Position data for a windowed projector, in Qt Base64 encoded format. Mutually exclusive with monitorIndex Monitor index, use GetMonitorList to obtain index. -1 to open in windowed mode Thrown if authentication fails Thrown when the server responds with an error Error Code of exception Constructor Exception Message /// Error Code OBS Websocket Dotnet interface WebSocket request timeout, represented as a TimeSpan object Current connection state Get basic OBS video information Saves a screenshot of a source to the filesystem. The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. **Compatible with inputs and scenes.** Name of the source to take a screenshot of Image compression format to use. Use `GetVersion` to get compatible image formats Path to save the screenshot file to. Eg. `C:\\Users\\user\\Desktop\\screenshot.png` Width to scale the screenshot to Height to scale the screenshot to Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use \"default\" (whatever that means, idk) Base64-encoded screenshot string Saves a screenshot of a source to the filesystem. The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. **Compatible with inputs and scenes.** Name of the source to take a screenshot of Image compression format to use. Use `GetVersion` to get compatible image formats Path to save the screenshot file to. Eg. `C:\\Users\\user\\Desktop\\screenshot.png` Base64-encoded screenshot string Executes hotkey routine, identified by hotkey unique name Unique name of the hotkey, as defined when registering the hotkey (e.g. "ReplayBuffer.Save") Triggers a hotkey using a sequence of keys. Main key identifier (e.g. OBS_KEY_A for key "A"). Available identifiers are here: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-hotkeys.h Optional key modifiers object. You can combine multiple key operators. e.g. KeyModifier.Shift | KeyModifier.Control Get the name of the currently active scene. Name of the current scene Set the current scene to the specified one The desired scene name Get OBS stats (almost the same info as provided in OBS' stats window) List every available scene A of objects describing each scene Get a list of scenes in the currently active profile Get the specified scene's transition override info Name of the scene to return the override info TransitionOverrideInfo Set specific transition override for a scene Name of the scene to set the transition override Name of the transition to use Duration in milliseconds of the transition if transition is not fixed. Defaults to the current duration specified in the UI if there is no current override and this value is not given If your code needs to perform multiple successive T-Bar moves (e.g. : in an animation, or in response to a user moving a T-Bar control in your User Interface), set release to false and call ReleaseTBar later once the animation/interaction is over. T-Bar position. This value must be between 0.0 and 1.0. Whether or not the T-Bar gets released automatically after setting its new position (like a user releasing their mouse button after moving the T-Bar). Call ReleaseTBar manually if you set release to false. Defaults to true. Apply settings to a source filter Source with filter Filter name JObject with filter settings Apply over existing settings? Apply settings to a source filter Source with filter Filter name Filter settings Apply over existing settings? Modify the Source Filter's visibility Source name Source filter name New filter state Return a list of all filters on a source Source name Return a list of settings for a specific filter Source name Filter name Remove the filter from a source Name of the source the filter is on Name of the filter to remove Add a filter to a source Name of the source for the filter Name of the filter Type of filter JObject holding filter settings object Add a filter to a source Name of the source for the filter Name of the filter Type of filter Filter settings object Toggles the status of the stream output. New state of the stream output Toggles the status of the record output. Gets the status of the stream output An object describing the current outputs states Get the current transition name and duration An object with the current transition name and duration Set the current transition to the specified one Desired transition name Change the transition's duration Desired transition duration (in milliseconds) Change the current settings of a transition Transition settings (they can be partial) Whether to overlay over the current settins or replace them Updated transition settings Change the volume of the specified source Name of the source which volume will be changed Desired volume. Must be between `0.0` and `1.0` for amplitude/mul (useDecibel is false), and under 0.0 for dB (useDecibel is true). Note: OBS will interpret dB values under -100.0 as Inf. Interperet `volume` data as decibels instead of amplitude/mul. Get the volume of the specified source Volume is between `0.0` and `1.0` if using amplitude/mul (useDecibel is false), under `0.0` if using dB (useDecibel is true). Source name An Object containing the volume and mute state of the specified source. Gets the audio mute state of an input. Name of input to get the mute state of Whether the input is muted Set the mute state of the specified source Name of the source which mute state will be changed Desired mute state Toggle the mute state of the specified source Name of the source which mute state will be toggled Sets the transform and crop info of a scene item Name of the scene that has the SceneItem Id of the Scene Item JObject holding transform settings Sets the transform and crop info of a scene item Name of the scene that has the SceneItem Id of the Scene Item Transform settings Set the current scene collection to the specified one Desired scene collection name Get the name of the current scene collection Name of the current scene collection List all scene collections A of the names of all scene collections Set the current profile to the specified one Name of the desired profile List all profiles A of the names of all profiles Start streaming. Will trigger an error if streaming is already active Stop streaming. Will trigger an error if streaming is not active. Start recording. Will trigger an error if recording is already active. Stop recording. Will trigger an error if recording is not active. File name for the saved recording Pause the current recording. Returns an error if recording is not active or already paused. Resume/unpause the current recording (if paused). Returns an error if recording is not active or not paused. Get the path of the current recording folder Current recording folder path Get current recording status. Get the status of the OBS replay buffer. Current recording status. true when active Get duration of the currently selected transition (if supported) Current transition duration (in milliseconds) Get status of Studio Mode Studio Mode status (on/off) Enables or disables studio mode Get the name of the currently selected preview scene. Note: Triggers an error if Studio Mode is disabled Preview scene name Change the currently active preview/studio scene to the one specified. Triggers an error if Studio Mode is disabled Preview scene name Change the currently active preview/studio scene to the one specified. Triggers an error if Studio Mode is disabled. Preview scene object Triggers the current scene transition. Same functionality as the `Transition` button in Studio Mode Toggles the state of the replay buffer output. Start recording into the Replay Buffer. Triggers an error if the Replay Buffer is already active, or if the "Save Replay Buffer" hotkey is not set in OBS' settings Stop recording into the Replay Buffer. Triggers an error if the Replay Buffer is not active. Save and flush the contents of the Replay Buffer to disk. Basically the same as triggering the "Save Replay Buffer" hotkey in OBS. Triggers an error if Replay Buffer is not active. Set the audio sync offset of the specified source Source name Audio offset (in nanoseconds) for the specified source Get the audio sync offset of the specified source Source name Audio offset (in nanoseconds) of the specified source Removes a scene item from a scene. Scenes only. Scene item id Scene name from which to delete item Sends CEA-608 caption text over the stream output. As of OBS Studio 23.1, captions are not yet available on Linux. Captions text Duplicates a scene item Name of the scene that has the SceneItem Id of the Scene Item Name of scene to add the new duplicated Scene Item. If not specified will assume sceneName Gets the names of all special inputs. Dictionary of special inputs. Sets the current stream service settings (stream destination). Note: Simple RTMP settings can be set with type `rtmp_custom` and the settings fields `server` and `key`. Stream Service Type Name and Settings objects Gets the current stream service settings (stream destination). Stream service type and settings objects Gets the audio monitor type of an input. The available audio monitor types are: - `OBS_MONITORING_TYPE_NONE` - `OBS_MONITORING_TYPE_MONITOR_ONLY` - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` Source name The monitor type in use Sets the audio monitor type of an input. Name of the input to set the audio monitor type of Audio monitor type. See `GetInputAudioMonitorType for possible types. Broadcasts a `CustomEvent` to all WebSocket clients. Receivers are clients which are identified and subscribed. Data payload to emit to all receivers Sets the cursor position of a media input. This request does not perform bounds checking of the cursor position. Name of the media input New cursor position to set (milliseconds). Offsets the current cursor position of a media input by the specified value. This request does not perform bounds checking of the cursor position. Name of the media input Value to offset the current cursor position by (milliseconds +/-) Creates a new input, adding it as a scene item to the specified scene. Name of the scene to add the input to as a scene item Name of the new input to created The kind of input to be created Jobject holding the settings object to initialize the input with Whether to set the created scene item to enabled or disabled ID of the SceneItem in the scene. Gets the default settings for an input kind. Input kind to get the default settings for Object of default settings for the input kind Gets a list of all scene items in a scene. Scenes only Name of the scene to get the items of Array of scene items in the scene Creates a new scene item using a source. Scenes only Name of the scene to create the new item in Name of the source to add to the scene Enable state to apply to the scene item on creation Numeric ID of the scene item Creates a new scene in OBS. Name for the new scene Gets the enable state of all audio tracks of an input. Name of the input Object of audio tracks and associated enable states Sets the enable state of audio tracks of an input. Name of the input JObject holding track settings to apply Sets the enable state of audio tracks of an input. Name of the input Track settings to apply Gets the active and show state of a source. **Compatible with inputs and scenes.** Name of the source to get the active state of Whether the source is showing in Program Gets the status of the virtualcam output. An object describing the current virtual camera state Starts the virtualcam output. Stops the virtualcam output. Toggles the state of the virtualcam output. Whether the output is active Gets the value of a \"slot\" from the selected persistent data realm. The data realm to select. `OBS_WEBSOCKET_DATA_REALM_GLOBAL` or `OBS_WEBSOCKET_DATA_REALM_PROFILE` The name of the slot to retrieve data from Value associated with the slot. `null` if not set Sets the value of a \"slot\" from the selected persistent data realm. The data realm to select. `OBS_WEBSOCKET_DATA_REALM_GLOBAL` or `OBS_WEBSOCKET_DATA_REALM_PROFILE` The name of the slot to retrieve data from The value to apply to the slot Creates a new scene collection, switching to it in the process.\n\nNote: This will block until the collection has finished changing. Name for the new scene collection Creates a new profile, switching to it in the process Name for the new profile Removes a profile. If the current profile is chosen, it will change to a different profile first. Name of the profile to remove Gets a parameter from the current profile's configuration. Category of the parameter to get Name of the parameter to get Sets the value of a parameter in the current profile's configuration. Category of the parameter to set Name of the parameter to set Value of the parameter to set. Use `null` to delete Sets the current video settings. Note: Fields must be specified in pairs. For example, you cannot set only `baseWidth` without needing to specify `baseHeight`. Object containing video settings Gets the default settings for a filter kind. Filter kind to get the default settings for Object of default settings for the filter kind Sets the name of a source filter (rename). Name of the source the filter is on Current name of the filter New name for the filter Sets the index position of a filter on a source. Name of the source the filter is on Name of the filter New index position of the filter Gets data about the current plugin and RPC version. Version info in an object Call a request registered to a vendor. A vendor is a unique name registered by a third-party plugin or script, which allows for custom requests and events to be added to obs-websocket. If a plugin or script implements vendor requests or events, documentation is expected to be provided with them. Name of the vendor to use The request type to call Object containing appropriate request data Object containing appropriate response data. {} if request does not provide any response data Gets an array of all hotkey names in OBS Array of hotkey names Sleeps for a time duration or number of frames. Only available in request batches with types `SERIAL_REALTIME` or `SERIAL_FRAME`. Number of milliseconds to sleep for (if `SERIAL_REALTIME` mode) Number of frames to sleep for (if `SERIAL_FRAME` mode) Gets an array of all inputs in OBS. Restrict the array to only inputs of the specified kind List of Inputs in OBS Gets an array of all available input kinds in OBS. True == Return all kinds as unversioned, False == Return with version suffixes (if available) Array of input kinds Removes an existing input. Note: Will immediately remove all associated scene items. Name of the input to remove Sets the name of an input (rename). Current input name New name for the input Gets the settings of an input. Note: Does not include defaults. To create the entire settings object, overlay `inputSettings` over the `defaultInputSettings` provided by `GetInputDefaultSettings`. Name of the input to get the settings of New populated InputSettings object Sets the settings of an input. Object of settings to apply True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. Sets the settings of an input. Name of the input to set the settings of Object of settings to apply True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. Gets the audio balance of an input. Name of the input to get the audio balance of Audio balance value from 0.0-1.0 Sets the audio balance of an input. Name of the input to set the audio balance of New audio balance value Gets the items of a list property from an input's properties. Note: Use this in cases where an input provides a dynamic, selectable list of items. For example, display capture, where it provides a list of available displays. Name of the input Name of the list property to get the items of Array of items in the list property Presses a button in the properties of an input. Note: Use this in cases where there is a button in the properties of an input that cannot be accessed in any other way. For example, browser sources, where there is a refresh button. Name of the input Name of the button property to press Gets the status of a media input.\n\nMedia States: - `OBS_MEDIA_STATE_NONE` - `OBS_MEDIA_STATE_PLAYING` - `OBS_MEDIA_STATE_OPENING` - `OBS_MEDIA_STATE_BUFFERING` - `OBS_MEDIA_STATE_PAUSED` - `OBS_MEDIA_STATE_STOPPED` - `OBS_MEDIA_STATE_ENDED` - `OBS_MEDIA_STATE_ERROR` Name of the media input Object containing string mediaState, int mediaDuration, int mediaCursor properties Triggers an action on a media input. Name of the media input Identifier of the `ObsMediaInputAction` enum Gets the filename of the last replay buffer save file. File path of last replay Toggles pause on the record output. Currently BROKEN in obs-websocket/obs-studio Basically GetSceneItemList, but for groups. Using groups at all in OBS is discouraged, as they are very broken under the hood. Groups only Name of the group to get the items of Array of scene items in the group Searches a scene for a source, and returns its id.\n\nScenes and Groups Name of the scene or group to search in Name of the source to find Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item Numeric ID of the scene item Gets the transform and crop info of a scene item. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Object containing scene item transform info Gets the JObject of transform settings for a scene item. Use this one you don't want it populated with default values. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Object containing scene item transform info Gets the enable state of a scene item. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Whether the scene item is enabled. `true` for enabled, `false` for disabled Gets the enable state of a scene item. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item New enable state of the scene item Gets the lock state of a scene item. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Whether the scene item is locked. `true` for locked, `false` for unlocked Sets the lock state of a scene item. Scenes and Group Name of the scene the item is in Numeric ID of the scene item New lock state of the scene item Gets the index position of a scene item in a scene. An index of 0 is at the bottom of the source list in the UI. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Index position of the scene item Sets the index position of a scene item in a scene. Scenes and Groups Name of the scene the item is in Numeric ID of the scene item New index position of the scene item Gets the blend mode of a scene item. Blend modes: - `OBS_BLEND_NORMAL` - `OBS_BLEND_ADDITIVE` - `OBS_BLEND_SUBTRACT` - `OBS_BLEND_SCREEN` - `OBS_BLEND_MULTIPLY` - `OBS_BLEND_LIGHTEN` - `OBS_BLEND_DARKEN` Scenes and Groups Name of the scene the item is in Numeric ID of the scene item Current blend mode Sets the blend mode of a scene item. Scenes and Groups Gets an array of all groups in OBS. Groups in OBS are actually scenes, but renamed and modified. In obs-websocket, we treat them as scenes where we can. Array of group names Removes a scene from OBS. Name of the scene to remove Sets the name of a scene (rename). Name of the scene to be renamed New name for the scene Gets a Base64-encoded screenshot of a source. The `imageWidth` and `imageHeight` parameters are treated as \"scale to inner\", meaning the smallest ratio will be used and the aspect ratio of the original resolution is kept. If `imageWidth` and `imageHeight` are not specified, the compressed image will use the full resolution of the source. **Compatible with inputs and scenes.** Name of the source to take a screenshot of Image compression format to use. Use `GetVersion` to get compatible image formats Width to scale the screenshot to Height to scale the screenshot to Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use \"default\" (whatever that means, idk) Base64-encoded screenshot Gets an array of all available transition kinds. Similar to `GetInputKindList` Array of transition kinds Gets the cursor position of the current scene transition. Note: `transitionCursor` will return 1.0 when the transition is inactive. Cursor position, between 0.0 and 1.0 Opens the properties dialog of an input. Name of the input to open the dialog of Opens the filters dialog of an input. Name of the input to open the dialog of Opens the interact dialog of an input. Name of the input to open the dialog of Gets a list of connected monitors and information about them. a list of detected monitors with some information Connect this instance to the specified URL, and authenticate (if needed) with the specified password. NOTE: Please subscribe to the Connected/Disconnected events (or atlease check the IsConnected property) to determine when the connection is actually fully established Server URL in standard URL format. Server password Connect this instance to the specified URL, and authenticate (if needed) with the specified password. NOTE: Please subscribe to the Connected/Disconnected events (or atleast check the IsConnected property) to determine when the connection is actually fully established Server URL in standard URL format. Server password Disconnect this instance from the server Sends a message to the websocket API with the specified request type and optional parameters obs-websocket request type, must be one specified in the protocol specification additional JSON fields if required by the request type The server's JSON response as a JObject Request authentication data. You don't have to call this manually. Authentication data in an object The current program scene has changed. The list of scenes has changed. TODO: Make OBS fire this event when scenes are reordered. Triggered when the scene item list of the specified scene is reordered Triggered when a new item is added to the item list of the specified scene Triggered when an item is removed from the item list of the specified scene Triggered when the visibility of a scene item changes Triggered when the lock status of a scene item changes Triggered when switching to another scene collection Triggered when a scene collection is created, deleted or renamed Triggered when switching to another transition Triggered when the current transition duration is changed Triggered when a transition between two scenes starts. Followed by Triggered when a transition (other than "cut") has ended. Please note that the from-scene field is not available in TransitionEnd Triggered when a stinger transition has finished playing its video Triggered when switching to another profile Triggered when a profile is created, imported, removed or renamed Triggered when the streaming output state changes Triggered when the recording output state changes Triggered when state of the replay buffer changes Triggered when the preview scene selection changes (Studio Mode only) Triggered when Studio Mode is turned on or off Triggered when OBS exits Triggered when connected successfully to an obs-websocket server Triggered when disconnected from an obs-websocket server A scene item is selected in the UI A scene item transform has changed The audio sync offset of an input has changed A filter was added to a source A filter was removed from a source Filters in a source have been reordered Triggered when the visibility of a filter has changed A source has been muted or unmuted The volume of a source has changed A custom broadcast message was received These events are emitted by the OBS sources themselves. For example when the media file ends. The behavior depends on the type of media source being used. These events are emitted by the OBS sources themselves. For example when the media file starts playing. The behavior depends on the type of media source being used. This event is only emitted when something actively controls the media/VLC source. In other words, the source will never emit this on its own naturally. The virtual cam state has changed. The current scene collection has begun changing. The current profile has begun changing. The name of a source filter has changed. An input has been created. An input has been removed. The name of an input has changed. An input's active state has changed. When an input is active, it means it's being shown by the program feed. An input's show state has changed. When an input is showing, it means it's being shown by the preview or a dialog. The audio balance value of an input has changed. The audio tracks of an input have changed. The monitor type of an input has changed. Available types are: - `OBS_MONITORING_TYPE_NONE` - `OBS_MONITORING_TYPE_MONITOR_ONLY` - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` A high-volume event providing volume levels of all active inputs every 50 milliseconds. The replay buffer has been saved. A new scene has been created. A scene has been removed. The name of a scene has changed. Event args for Name of the scene that was switched to Default Constructor The scene name Event args for Name of the new profile Default Constructor The profile name Event args for Name of the current profile Default Constructor The profile name Event args for Name of the new scene collection Default Constructor The scene collection name Event args for Name of the current scene collection Default Constructor The scene collection name Event args for Name of the new transition Default Constructor The transition name Event args for Transition duration in milliseconds Default Constructor The transition duration Event args for Name of the input Whether the input is active Default Constructor The input name Is the video active Event args for Name of the affected input New audio balance value of the input Default Constructor The input name The input audio balance Event args for Available types are: - `OBS_MONITORING_TYPE_NONE` - `OBS_MONITORING_TYPE_MONITOR_ONLY` - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` Name of the input New monitor type of the input Default Constructor The input name The monitor type Event args for Name of the input New sync offset in milliseconds Default Constructor The input name The input audio sync offset Event args for Name of the input Object of audio tracks along with their associated enable states Default Constructor The input name The audio track data as a JObject Event args for Name of the input The kind of the input The unversioned kind of input (aka no `_v2` stuff) The settings configured to the input when it was created The default settings for the input Default Constructor The input name The kind of input The unversioned kind of input The input settings as a JObject The default input settings as a JObject Event args for Name of the input Whether the input is muted Default Constructor The input name Is the input muted Event args for Old name of the input New name of the input Default Constructor The old input name The new input name Event args for Name of the input Default Constructor The input name Event args for Name of the input Whether the input is showing Default Constructor The input name Is the video showing Event args for Current volume levels of source Default Constructor The new input volume Event args for Array of active inputs with their associated volume levels Default Constructor Collection inputs as JObjects Event args for Name of the input Action performed on the input. See `ObsMediaInputAction` enum Default Constructor The input name The media action data Event args for Name of the input Default Constructor The input name Event args for Name of the input Default Constructor The input name Event args for The profiles that have changed Default Constructor Collection of profile names as strings Event args for The new scene name Default Constructor The scene name Event args for The specific state of the output Default Constructor The record state change data Event args for Path of the saved replay file Default Constructor The saved replay path Event args for The specific state of the output Default constructor Specific state of the output Event args for Updated list of scene collections Default Constructor Collection of scene collection names as string Event args for Name of the new scene Whether the new scene is a group Default Constructor The scene name Is the scene item a group Event args for Name of the scene where the item is Name of the concerned item Numeric ID of the scene item Index position of the item Default Constructor The scene name The source name The scene item id The scene item index Event args for Name of the scene the item is in Numeric ID of the scene item Whether the scene item is enabled (visible) Default Constructor The scene name The scene item id Is the scene item enabled Event args for Name of the scene where items where reordered List of all scene items as JObject Default Constructor The scene name The scene item data as a colleciton of JObjects Event args for Name of the scene the item is in Numeric ID of the scene item Whether the scene item is locked (visible) Default Constructor The scene name The scene item id is the scene item locked Event args for Name of the scene where the item was removed from Name of the concerned item Numeric ID of the scene item Default Constructor The scene name The source name The scene items id Event args for Name of the scene item is in Numeric ID of the scene item Default Constructor The scene name The scene item id Event args for Name of the scene item is in Numeric ID of the scene item Transform data Default Constructor The scene name The scene item id The transform data Event args for Updated array of scenes Default Constructor Collection of scene data as JObjects Event args for Old name of the scene New name of the scene Default Constructor The previous scene name The new scene name Event args for Name of the removed scene Whether the removed scene was a group Default Constructor The scene name Is the scene name a group Event args for Scene transition name Default Constructor The transition name Event args for Transition name Default Constructor The transition name Called by Transition name Default Constructor The transition name Event args for Name of the source the filter was added to Name of the filter The kind of the filter Index position of the filter The settings configured to the filter when it was created The default settings for the filter Default Constructor The source name The filter name The kind of filter The index of the filter The filters settings as a JObject The default filter settings as a JObject Event args for Name of the source the filter is on Name of the filter Whether the filter is enabled Default Constructor The source name The filter name If the filter is enabled or not Event args for Name of the source Array of filter objects Default Constructor The source name Collection of filters Event args for The source the filter is on Old name of the filter New name of the filter Default Constructor The source name The filters previous name The filters new name Event args for Name of the source the filter was on Name of the filter Default Constructor The source name The filter name that's been removed Event args for The specific state of the output Default Constructor The output state data Event args for New Studio Mode status Default Constructor Is studio mode enabled Event args for unsupported events The type of the event The body of the event Event args for unsupported events Event args for Name of the vendor emitting the event Vendor-provided event typedef Vendor-provided event data. {} if event does not provide any data Default Constructor The vendor name The event type The event data as a Json Object Event args for The specific state of the output Default Constructor The output state data Filter list item Name of filter Type of filter Filter settings Name of the filter Type of the specified filter Index of the filter in the list, beginning at 0 Status of the specified filter Settings for the filter Response from Name of the currently active profile List of all profiles Response from Name of the currently active program scene Name of the currently active preview/studio scene Note: Will return null if not in studio mode Ordered list of the current profile's scenes Response from Name of the currently active transition Kind of the currently active transition List of transitions. Abstract class with information on a specific Input Name of the Input Kind of the Input Instantiate object from response data Default Constructor Input class which also shows the Unversioned Input Kind Unversioned Kind of the Input Instantiate object from response data Default Constructor Input class dedicated for the ffmpeg_source input kind. Usage: InputBrowserSourceSettings.FromInputSettings(InputSettings) Set a custom FPS (using the FPS property) Frames Per Second Control audio via OBS Height Width Custom CSS Is Local file Local filename (when IsLocalFile is true) URL (when IsLocalFile is false) Refresh browser when scene becomes active Shutdown source when not visible Page Permissions Static constructor to instanciate a InputBrowserSourceSettings object Requires an InputSettings class with InputKind of browser_source to create Settings object Input class dedicated for the ffmpeg_source input kind. Usage: InputFFMpegSettings.FromInputSettings(InputSettings) Buffering MB Clear window when media ends Close when inactive Color Range HW Decoder Is Local file Local filename Looping Apply alpha in linear space Restart when activated ffmpeg options Speed percentage Static constructor to instanciate a InputFFMpegSettings object Requires an InputSettings class with InputKind of ffmpeg_source to create Setings object Settings for a source item Settings for the source Builds the object from the JSON data JSON item description as a Default Constructor for deserialization Source volume values Name of the source The source volume in percent The source volume in decibels Builds the object from the JSON response body JSON response body as a Empty constructor for jsonconvert Key Modifiers No modifiers Shift Key Alt Key Control Key Command (Mac) / WinKey (?) Windows Status of a Media Input State of the media input State of the media input Total duration of the playing media in milliseconds. `null` if not playing Position of the cursor in milliseconds. `null` if not playing Instantiate from JObject Default Constructor Enum representing the state of a media input No media is loaded Media is playing Media is opening Media is buffering Media is playing but is paused Media is stopped Media is ended Media has errored Information on a connected Monitor Monitor height (px) Monitor width (px) Monitor Name Monitor Index Monitor Position X Monitor Position Y Constructor to auto populate Default Constructor OBS Hotkeys as defined here: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-hotkeys.h Describes a scene in OBS, along with its items OBS Scene name Is group Scene item list Builds the object from the JSON description JSON scene description as a Default Constructor for deserialization OBS Stats Current framerate. Number of frames rendered Number of frames missed due to rendering lag Number of frames outputted Number of frames skipped due to encoding lag Average frame render time (in milliseconds) Current CPU usage (percentage) Current RAM usage (in megabytes) Free recording disk space (in megabytes) Total number of messages received by obs-websocket from the client Total number of messages sent by obs-websocket to the client Version info of the plugin, the API and OBS Studio obs-websocket plugin version OBS Studio version OBSRemote compatible API version.Fixed to 1.1 for retrocompatibility. List of available request types, formatted as a comma-separated list string (e.g. : "Method1,Method2,Method3"). Image formats available in `GetSourceScreenshot` and `SaveSourceScreenshot` requests. Name of the platform. Usually `windows`, `macos`, or `ubuntu` (linux flavor). Not guaranteed to be any of those Description of the platform, like `Windows 10 (10.0)` Builds the object from the JSON response body JSON response body as a Empty constructor for jsonconvert Basic OBS video information Numerator of the fractional FPS value Denominator of the fractional FPS value Base (canvas) width Base (canvas) height Width of the output resolution in pixels Height of the output resolution in pixels Describes the state of an output (streaming or recording) The output is initializing and doesn't produce frames yet The output is running and produces frames The output is stopping and sends the last remaining frames in its buffer The output is completely stopped The output is paused (usually recording output) The output is resumed (i.e. no longer paused) - usually recording output Data when Stream/Recording/Instant_Replay change states Is output currently active (streaming/recording) Output state as string OutputState enum of current state Constructor Default Constructor for deserialization Status of streaming output True if streaming is started and running, false otherwise Whether the output is currently reconnectins Current formatted timecode string for the output Current duration in milliseconds for the output Congestion of the output Nubmer of bytes sent by the output Number of frames skipped by the output's process Total number of frames delivered by the output's process Builds the object from the JSON response body JSON response body as a Default Constructor for deserialization GetRecordingStatus response Current recording status Whether the recording is paused or not Current formatted timecode string for the output Current duration in milliseconds for the output Number of bytes sent by the output Builds the object from the JSON response body JSON response body as a Default Constructor for deserialization Data when Recording change states File name for the saved recording, if record stopped. null otherwise Constructor Default Constructor for deserialization Response from Name of scene Index of scene Types of bounding boxes for scene items Stretch Inner scale Outer scale Scale to width Scale to height Max only No bounds Meta data regarding a Scene item Unique item id of the source item Kind of source (Example: vlc_source or image_source) Name of the scene item's source Type of the scene item's source. Builds the object from the JSON data JSON item description as a Default Constructor for deserialization Type of scene item's source Input Filter Transition Scene Item transformation information Alignment of the item The point on the scene item that the item is manipulated from Height of the bounding box Width of the bounding box Type of bounding box Bottom crop (in pixels) Left crop (in pixels) Right crop (in pixels) Top crop (in pixels) The clockwise rotation of the scene item in degrees around the point of alignment. The x-scale factor of the scene item The y-scale factor of the scene item Base height (without scaling) of the source Base width (without scaling) of the source Scene item height (base source height multiplied by the vertical scaling factor) Scene item width (base source width multiplied by the horizontal scaling factor) The x position of the scene item from the left The y position of the scene item from the top Initialize the scene item transform Default Constructor for deserialization Gets the Active and Showing state of a video source Whether the source is showing in Program Whether the source is showing in the UI (Preview, Projector, Properties) Auto populate constructor Default Constructor Tracks status for a source item Is the track active Is the track active Is the track active Is the track active Is the track active Is the track active Builds the object from the JSON data JSON item description as a Default Constructor for deserialization Streaming settings Type of streaming service Streaming service settings (JSON data) Streaming server settings The publish URL The publish key of the stream Indicates whether authentication should be used when connecting to the streaming server The username to use when accessing the streaming server. Only present if use-auth is true The password to use when accessing the streaming server. Only present if use-auth is true The service being used to stream The protocol to use for the stream Other values not covered by the class Scene transition override settings Name of the current overriding transition. Empty string if no override is set. Transition duration in milliseconds. -1 if no override is set. Current transition settings Transition name Transition duration in milliseconds Kind of the transition Whether the transition uses a fixed (unconfigurable) duration Whether the transition supports being configured Object of settings for the transition. 'null' if transition is not configurable Builds the object from the JSON response body JSON response body as a Default Constructor for deserialization VirtualCam Status Whether the output is active Builds the object from the JSON response body JSON response body as a Constructor for jsonconverter Volume settings of an OBS source Source volume in linear scale (0.0 to 1.0) Volume setting in dB Builds the object from the JSON response body JSON response body as a Default Constructor for deserialization ================================================ FILE: obs-websocket-dotnet-tests/UnitTest_OBSWebsocket.cs ================================================ using Microsoft.VisualStudio.TestTools.UnitTesting; using WebSocketSharp; namespace OBSWebsocketDotNet.Tests { [TestClass] public class UnitTest_OBSWebsocket : OBSWebsocket { [TestMethod] public void NewMessageID_Test() { int idLength = 22; string msgID = NewMessageID(idLength); Assert.IsFalse(msgID.IsNullOrEmpty()); Assert.AreEqual(idLength, msgID.Length); } [TestMethod] public void HashEncode_Test() { string sourceText, expectedResult, result; // First test sourceText = "The quick brown fox jumps over the lazy dog."; expectedResult = "71N/JciVv6eCUmUpqbY9l6pjFWTV14nCt2VEjIY1+2w="; result = HashEncode(sourceText); Assert.AreEqual(expectedResult, result); // Second test : consecutive calls produce same output // for a given source text Assert.AreEqual(result, HashEncode(sourceText)); // Third test : another source text sourceText = "Pack my box with five dozen liquor jugs."; expectedResult = "I+7lK59W6o/nkmE65aY5TE13mBTi/AfgndWWjUqu3cw="; result = HashEncode(sourceText); Assert.AreEqual(expectedResult, result); } } } ================================================ FILE: obs-websocket-dotnet-tests/UnitTest_Types.cs ================================================ using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; using OBSWebsocketDotNet.Communication; using OBSWebsocketDotNet.Types; namespace OBSWebsocketDotNet.Tests { [TestClass] public class UnitTest_Types { [TestMethod] public void OBSScene_BuildFromJSON() { string sceneName = "Scene name äëôû"; bool isGroup = true; string itemName = "First item name äëôû"; SceneItemSourceType sourceType = SceneItemSourceType.OBS_SOURCE_TYPE_INPUT; string inputKind = "BarRaider"; int sceneItemId = 22; JObject itemData = new JObject { { "sourceName", itemName }, { "sourceType", (int)sourceType }, { "inputKind", inputKind}, { "sceneItemId", sceneItemId }, { "volume", 1.0f }, { "x", 0.0f }, { "y", 0.0f }, { "source_cx", 1280 }, { "source_cy", 720 }, { "cx", 1280.0f }, { "cy", 720.0F } }; var items = new JArray { itemData }; var data = new JObject { { "sceneName", sceneName }, { "sources", items }, { "isGroup", isGroup } }; var scene = new ObsScene(data); Assert.AreEqual(sceneName, scene.Name); Assert.AreEqual(1, scene.Items.Count); Assert.AreEqual(isGroup, scene.IsGroup); Assert.AreEqual(itemName, scene.Items[0].SourceName); Assert.AreEqual(sourceType, scene.Items[0].SourceType); Assert.AreEqual(inputKind, scene.Items[0].SourceKind); Assert.AreEqual(sceneItemId, scene.Items[0].ItemId); } [TestMethod] public void OBSAuthInfo_BuildFromJSON() { string challenge = "pBWv82hj"; string salt = "B9fL8CF7"; var data = new JObject { { "authRequired", true }, { "challenge", challenge }, { "salt", salt } }; var authInfo = new OBSAuthInfo(data); Assert.AreEqual(challenge, authInfo.Challenge); Assert.AreEqual(salt, authInfo.PasswordSalt); } [TestMethod] public void OBSVersion_BuildFromJSON() { string pluginVersion = "5.0.1"; string obsVersion = "28.0.1"; double rpcVersion = 1.1; string availableRequests = "GetVersion,BarRaider,Test"; string platform = "windows"; string supportedImageFormats = "png,jpg"; var requests = new JArray(availableRequests.Split(',')); var images = new JArray(supportedImageFormats.Split(',')); var data = new JObject { { "obsWebSocketVersion", pluginVersion }, { "obsVersion", obsVersion }, { "rpcVersion", rpcVersion}, { "availableRequests", requests}, { "platform", platform}, { "supportedImageFormats", images} }; var version = new ObsVersion(data); Assert.AreEqual(pluginVersion, version.PluginVersion); Assert.AreEqual(obsVersion, version.OBSStudioVersion); Assert.AreEqual(rpcVersion, version.Version); Assert.AreEqual(platform, version.Platform); Assert.AreEqual(3, version.AvailableRequests.Count); Assert.AreEqual(2, version.SupportedImageFormats.Count); } [TestMethod] public void OBSStreamStatus_BuildFromJSON() { string outputTimecode = "00:01:22.666"; int outputDuration = 230; double outputCongestion = 23.32; int outputBytes = 451241; int outputSkippedFrames = 120; int outputTotalFrames = 2000; var data = new JObject { { "outputActive", true }, { "outputReconnecting", true }, { "outputTimecode", outputTimecode }, { "outputDuration", outputDuration }, { "outputCongestion", outputCongestion }, { "outputBytes", outputBytes }, { "outputSkippedFrames", outputSkippedFrames }, { "outputTotalFrames", outputTotalFrames } }; var streamStatus = new OutputStatus(data); Assert.IsTrue(streamStatus.IsActive); Assert.IsTrue(streamStatus.IsReconnecting); Assert.AreEqual(outputTimecode, streamStatus.TimeCode); Assert.AreEqual(outputDuration, streamStatus.Duration); Assert.AreEqual(outputCongestion, streamStatus.Congestion); Assert.AreEqual(outputBytes, streamStatus.BytesSent); Assert.AreEqual(outputSkippedFrames, streamStatus.SkippedFrames); Assert.AreEqual(outputTotalFrames, streamStatus.TotalFrames); } [TestMethod] public void OBSOutputStatus_BuildFromJSON() { var data = new JObject { { "outputActive", true } }; var outputState = new OutputStatus(data); var recordState = new RecordingStatus(data); Assert.IsTrue(outputState.IsActive); Assert.IsTrue(recordState.IsRecording); } [TestMethod] public void OBSCurrentTransitionInfo_BuildFromJSON() { string transitionName = "Transition name éèïöü"; int duration = 2000; string kind = "TBD"; bool transitionFixed = true; bool transitionConfigurable = true; var data = new JObject { { "transitionName", transitionName }, { "transitionDuration", duration }, { "transitionKind", kind }, { "transitionFixed", transitionFixed }, { "transitionConfigurable", transitionConfigurable } }; var transitionInfo = new TransitionSettings(data); Assert.AreEqual(transitionName, transitionInfo.Name); Assert.AreEqual(duration, transitionInfo.Duration); Assert.AreEqual(kind, transitionInfo.Kind); Assert.AreEqual(transitionFixed, transitionInfo.IsFixed); Assert.AreEqual(transitionConfigurable, transitionInfo.IsConfigurable); } [TestMethod] public void OBSVolumeInfo_BuildFromJSON() { float volumeMul = 0.50f; float volumeDB = 45.4f; var data = new JObject { { "inputVolumeMul", volumeMul }, { "inputVolumeDb", volumeDB } }; var volumeInfo = new VolumeInfo(data); Assert.AreEqual(volumeMul, volumeInfo.VolumeMul); Assert.AreEqual(volumeDB, volumeInfo.VolumeDb); } } } ================================================ FILE: obs-websocket-dotnet-tests/obs-websocket-dotnet-tests.csproj ================================================  net9.0 obs-websocket-dotnet-tests OBSWebsocketDotNet.Tests Copyright © Stéphane Lepin, BarRaider 2021 8 ================================================ FILE: obs-websocket-dotnet-tests/packages.config ================================================  ================================================ FILE: obs-websocket-dotnet.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30503.244 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "obs-websocket-dotnet", "obs-websocket-dotnet\obs-websocket-dotnet.csproj", "{C8668815-F21E-49C0-8F1A-58BC698153AF}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestClient", "TestClient\TestClient.csproj", "{2CB2A741-4BFB-4AE8-894B-D6F146E6670F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "obs-websocket-dotnet-tests", "obs-websocket-dotnet-tests\obs-websocket-dotnet-tests.csproj", "{107BEC4B-3EC4-4CA0-A53F-7D3678DC7017}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {C8668815-F21E-49C0-8F1A-58BC698153AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C8668815-F21E-49C0-8F1A-58BC698153AF}.Debug|Any CPU.Build.0 = Debug|Any CPU {C8668815-F21E-49C0-8F1A-58BC698153AF}.Release|Any CPU.ActiveCfg = Release|Any CPU {C8668815-F21E-49C0-8F1A-58BC698153AF}.Release|Any CPU.Build.0 = Release|Any CPU {2CB2A741-4BFB-4AE8-894B-D6F146E6670F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2CB2A741-4BFB-4AE8-894B-D6F146E6670F}.Debug|Any CPU.Build.0 = Debug|Any CPU {2CB2A741-4BFB-4AE8-894B-D6F146E6670F}.Release|Any CPU.ActiveCfg = Release|Any CPU {2CB2A741-4BFB-4AE8-894B-D6F146E6670F}.Release|Any CPU.Build.0 = Release|Any CPU {107BEC4B-3EC4-4CA0-A53F-7D3678DC7017}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {107BEC4B-3EC4-4CA0-A53F-7D3678DC7017}.Debug|Any CPU.Build.0 = Debug|Any CPU {107BEC4B-3EC4-4CA0-A53F-7D3678DC7017}.Release|Any CPU.ActiveCfg = Release|Any CPU {107BEC4B-3EC4-4CA0-A53F-7D3678DC7017}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DB456FB4-3420-4299-8634-335D28DCCC51} EndGlobalSection EndGlobal