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
 Releases: [](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