diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
new file mode 100644
index 0000000..a7ce38b
--- /dev/null
+++ b/.config/dotnet-tools.json
@@ -0,0 +1,12 @@
+{
+ "version": 1,
+ "isRoot": true,
+ "tools": {
+ "dotnet-warp": {
+ "version": "1.1.0",
+ "commands": [
+ "dotnet-warp"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml
new file mode 100644
index 0000000..fcf8f55
--- /dev/null
+++ b/.github/workflows/release-action.yml
@@ -0,0 +1,79 @@
+name: Release PresentationObsSceneSwitcher
+
+on:
+ push:
+ tags:
+ - 'v*'
+
+jobs:
+
+ build:
+ 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: PresentationObsSceneSwitcherConsole
+ ProjectDirectory: PresentationObsSceneSwitcherConsole
+ FileName: PresentationObsSceneSwitcher
+ ProjectPath: PresentationObsSceneSwitcherConsole\PresentationObsSceneSwitcherConsole.csproj
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ # Install the .NET Core workload
+ - name: Install .NET Core
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: 3.1.101
+
+ # Restore tools
+ - name: Restore tools
+ run: dotnet tool restore
+
+ # Restore the application to populate the obj folder with RuntimeIdentifiers
+ - name: Restore the application
+ run: dotnet restore $env:ProjectPath
+
+ # Decode the base 64 encoded pfx and save the Signing_Certificate
+ - name: Build
+ run: |
+ mkdir ${{ env.ProjectDirectory }}\publish
+ dotnet warp $env:ProjectPath -o ${{ env.ProjectDirectory }}\publish\${{ env.FileName }}.exe
+
+ # Publish
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v2
+ with:
+ name: Exe
+ path: ${{ env.ProjectDirectory }}\publish
+
+ # Zip
+ - name: Zip
+ run: |
+ cd ${{ env.ProjectDirectory }}\publish
+ Compress-Archive -DestinationPath ${{ env.FileName }} -Path .\*
+
+ - name: Create Release
+ id: create_release
+ uses: actions/create-release@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: ${{ github.ref }}
+ release_name: Release ${{ github.ref }}
+ draft: false
+ prerelease: false
+
+ - name: Upload Release Asset
+ id: upload-release-asset
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
+ asset_path: ${{ env.ProjectDirectory }}\publish\PresentationObsSceneSwitcher.zip
+ asset_name: PresentationObsSceneSwitcher.zip
+ asset_content_type: application/zip
\ No newline at end of file
diff --git a/OBS.cs b/OBS.cs
index e82d390..ee968bc 100644
--- a/OBS.cs
+++ b/OBS.cs
@@ -25,6 +25,20 @@ public bool ChangeScene(string scene)
return true;
}
+ public bool StartRecording()
+ {
+ try { _OBS.Api.StartRecording(); }
+ catch { /* Recording already started */ }
+ return true;
+ }
+
+ public bool StopRecording()
+ {
+ try { _OBS.Api.StopRecording(); }
+ catch { /* Recording already stopped */ }
+ return true;
+ }
+
protected virtual void Dispose(bool disposing)
{
if (!_DisposedValue)
diff --git a/PowerPointInterop/PowerPoint.cs b/PowerPointInterop/PowerPoint.cs
new file mode 100644
index 0000000..25dd196
--- /dev/null
+++ b/PowerPointInterop/PowerPoint.cs
@@ -0,0 +1,27 @@
+using Microsoft.Office.Interop.PowerPoint;
+using System;
+using System.Threading.Tasks;
+
+namespace PowerPointInterop
+{
+ ///
+ /// This projects allows you to compile a .dll with an embed COM Reference.
+ /// Used to add compilation support using dotnet cli as it doesn't allow you to use COMReference.
+ ///
+ public static class PowerPoint
+ {
+ private static Application powerPoint = new Application();
+
+ public static void SubscribeSlideShowNextSlide(Func subscription)
+ {
+ powerPoint.SlideShowNextSlide += async (SlideShowWindow Wn) =>
+ {
+ var command = String.Empty;
+ try { command = Wn.View.Slide.NotesPage.Shapes[2].TextFrame.TextRange.Text; }
+ catch { /*no notes*/ }
+
+ await subscription(command);
+ };
+ }
+ }
+}
diff --git a/PowerPointInterop/PowerPointInterop.csproj b/PowerPointInterop/PowerPointInterop.csproj
new file mode 100644
index 0000000..bb76c8f
--- /dev/null
+++ b/PowerPointInterop/PowerPointInterop.csproj
@@ -0,0 +1,19 @@
+
+
+
+ netstandard2.0
+
+
+
+
+ {91493440-5a91-11cf-8700-00aa0060263b}
+ 2
+ 12
+ primary
+ 0
+ false
+ True
+
+
+
+
diff --git a/PowerPointInterop/README.md b/PowerPointInterop/README.md
new file mode 100644
index 0000000..0d0b855
--- /dev/null
+++ b/PowerPointInterop/README.md
@@ -0,0 +1 @@
+This projects allows you to compile a .dll with an embed COM Reference. Used to add compilation support using dotnet cli as it doesn't allow you to use COMReference.
diff --git a/PowerPointToOBSSceneSwitcher.csproj b/PowerPointToOBSSceneSwitcher.csproj
index 75b9f85..e51fe00 100644
--- a/PowerPointToOBSSceneSwitcher.csproj
+++ b/PowerPointToOBSSceneSwitcher.csproj
@@ -1,24 +1,36 @@
-
-
-
- Exe
- netcoreapp3.1
-
-
-
-
- {91493440-5a91-11cf-8700-00aa0060263b}
- 2
- 12
- primary
- 0
- false
- True
-
-
-
-
-
-
-
-
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {91493440-5a91-11cf-8700-00aa0060263b}
+ 2
+ 12
+ primary
+ 0
+ false
+ True
+
+
+
+
diff --git a/PowerPointToOBSSceneSwitcher.sln b/PowerPointToOBSSceneSwitcher.sln
index e2cad97..472cb50 100644
--- a/PowerPointToOBSSceneSwitcher.sln
+++ b/PowerPointToOBSSceneSwitcher.sln
@@ -1,25 +1,49 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30428.66
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerPointToOBSSceneSwitcher", "PowerPointToOBSSceneSwitcher.csproj", "{8A844363-5A92-403B-90CD-BFCB30ED5054}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {8A844363-5A92-403B-90CD-BFCB30ED5054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {8A844363-5A92-403B-90CD-BFCB30ED5054}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {8A844363-5A92-403B-90CD-BFCB30ED5054}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {8A844363-5A92-403B-90CD-BFCB30ED5054}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {515C02C0-0CF2-4890-A1FB-4D6A5F115CD6}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30428.66
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerPointToOBSSceneSwitcher", "PowerPointToOBSSceneSwitcher.csproj", "{8A844363-5A92-403B-90CD-BFCB30ED5054}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PresentationObsSceneSwitcher", "PresentationObsSceneSwitcher\PresentationObsSceneSwitcher.csproj", "{5B07EF15-11D6-4646-8322-965BD7D4ADEE}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{76FD753E-6BFA-477C-BA87-23D96C053DC5}"
+ ProjectSection(SolutionItems) = preProject
+ .config\dotnet-tools.json = .config\dotnet-tools.json
+ .github\workflows\release-action.yml = .github\workflows\release-action.yml
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerPointInterop", "PowerPointInterop\PowerPointInterop.csproj", "{6D327EF6-B794-4441-8893-3EFD05DA682F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PresentationObsSceneSwitcherConsole", "PresentationObsSceneSwitcherConsole\PresentationObsSceneSwitcherConsole.csproj", "{557DE28E-D0A2-4DFB-82F7-D7A32EB96C0C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8A844363-5A92-403B-90CD-BFCB30ED5054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8A844363-5A92-403B-90CD-BFCB30ED5054}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8A844363-5A92-403B-90CD-BFCB30ED5054}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8A844363-5A92-403B-90CD-BFCB30ED5054}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5B07EF15-11D6-4646-8322-965BD7D4ADEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5B07EF15-11D6-4646-8322-965BD7D4ADEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5B07EF15-11D6-4646-8322-965BD7D4ADEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5B07EF15-11D6-4646-8322-965BD7D4ADEE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6D327EF6-B794-4441-8893-3EFD05DA682F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6D327EF6-B794-4441-8893-3EFD05DA682F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6D327EF6-B794-4441-8893-3EFD05DA682F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6D327EF6-B794-4441-8893-3EFD05DA682F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {557DE28E-D0A2-4DFB-82F7-D7A32EB96C0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {557DE28E-D0A2-4DFB-82F7-D7A32EB96C0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {557DE28E-D0A2-4DFB-82F7-D7A32EB96C0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {557DE28E-D0A2-4DFB-82F7-D7A32EB96C0C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {515C02C0-0CF2-4890-A1FB-4D6A5F115CD6}
+ EndGlobalSection
+EndGlobal
diff --git a/PresentationObsSceneSwitcher/ConfigurationForm.Designer.cs b/PresentationObsSceneSwitcher/ConfigurationForm.Designer.cs
new file mode 100644
index 0000000..11f4f41
--- /dev/null
+++ b/PresentationObsSceneSwitcher/ConfigurationForm.Designer.cs
@@ -0,0 +1,222 @@
+
+namespace PresentationObsSceneSwitcher
+{
+ partial class ConfigurationForm
+ {
+ ///
+ /// 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.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ConfigurationForm));
+ this.panel1 = new System.Windows.Forms.Panel();
+ this.tbPassword = new System.Windows.Forms.TextBox();
+ this.label4 = new System.Windows.Forms.Label();
+ this.buttonStart = new System.Windows.Forms.Button();
+ this.tbPort = new System.Windows.Forms.TextBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this.tbIpAddress = new System.Windows.Forms.TextBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.label1 = new System.Windows.Forms.Label();
+ this.menuStrip = new System.Windows.Forms.MenuStrip();
+ this.menuItemClose = new System.Windows.Forms.ToolStripMenuItem();
+ this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
+ this.panel1.SuspendLayout();
+ this.menuStrip.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // panel1
+ //
+ this.panel1.BackColor = System.Drawing.Color.WhiteSmoke;
+ this.panel1.Controls.Add(this.tbPassword);
+ this.panel1.Controls.Add(this.label4);
+ this.panel1.Controls.Add(this.buttonStart);
+ this.panel1.Controls.Add(this.tbPort);
+ this.panel1.Controls.Add(this.label3);
+ this.panel1.Controls.Add(this.tbIpAddress);
+ this.panel1.Controls.Add(this.label2);
+ this.panel1.Controls.Add(this.label1);
+ this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.panel1.Location = new System.Drawing.Point(0, 25);
+ this.panel1.Margin = new System.Windows.Forms.Padding(10);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(329, 150);
+ this.panel1.TabIndex = 0;
+ //
+ // tbPassword
+ //
+ this.tbPassword.Location = new System.Drawing.Point(93, 72);
+ this.tbPassword.Margin = new System.Windows.Forms.Padding(5, 10, 10, 0);
+ this.tbPassword.Name = "tbPassword";
+ this.tbPassword.Size = new System.Drawing.Size(224, 25);
+ this.tbPassword.TabIndex = 7;
+ this.tbPassword.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(9, 75);
+ this.label4.Margin = new System.Windows.Forms.Padding(0, 10, 0, 0);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(67, 17);
+ this.label4.TabIndex = 6;
+ this.label4.Text = "Password:";
+ //
+ // buttonStart
+ //
+ this.buttonStart.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(85)))), ((int)(((byte)(85)))), ((int)(((byte)(85)))));
+ this.buttonStart.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.buttonStart.ForeColor = System.Drawing.Color.WhiteSmoke;
+ this.buttonStart.Location = new System.Drawing.Point(9, 107);
+ this.buttonStart.Margin = new System.Windows.Forms.Padding(0, 10, 0, 0);
+ this.buttonStart.Name = "buttonStart";
+ this.buttonStart.Size = new System.Drawing.Size(308, 30);
+ this.buttonStart.TabIndex = 5;
+ this.buttonStart.Text = "Start / Restart";
+ this.buttonStart.UseVisualStyleBackColor = false;
+ this.buttonStart.Click += new System.EventHandler(this.buttonStart_Click);
+ //
+ // tbPort
+ //
+ this.tbPort.Location = new System.Drawing.Point(269, 37);
+ this.tbPort.Margin = new System.Windows.Forms.Padding(5, 10, 0, 0);
+ this.tbPort.Name = "tbPort";
+ this.tbPort.Size = new System.Drawing.Size(48, 25);
+ this.tbPort.TabIndex = 4;
+ this.tbPort.Text = "4444";
+ this.tbPort.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(185, 40);
+ this.label3.Margin = new System.Windows.Forms.Padding(0, 10, 0, 0);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(79, 17);
+ this.label3.TabIndex = 3;
+ this.label3.Text = "Ip Address*:";
+ //
+ // tbIpAddress
+ //
+ this.tbIpAddress.Location = new System.Drawing.Point(93, 37);
+ this.tbIpAddress.Margin = new System.Windows.Forms.Padding(5, 10, 10, 0);
+ this.tbIpAddress.Name = "tbIpAddress";
+ this.tbIpAddress.Size = new System.Drawing.Size(82, 25);
+ this.tbIpAddress.TabIndex = 2;
+ this.tbIpAddress.Text = "127.0.0.1";
+ this.tbIpAddress.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(9, 40);
+ this.label2.Margin = new System.Windows.Forms.Padding(0, 10, 0, 0);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(79, 17);
+ this.label2.TabIndex = 1;
+ this.label2.Text = "Ip Address*:";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
+ this.label1.Location = new System.Drawing.Point(9, 10);
+ this.label1.Margin = new System.Windows.Forms.Padding(0);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(152, 17);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "OBS Websocket Server:";
+ //
+ // menuStrip
+ //
+ this.menuStrip.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(85)))), ((int)(((byte)(85)))), ((int)(((byte)(85)))));
+ this.menuStrip.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
+ this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.menuItemClose});
+ this.menuStrip.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip.Name = "menuStrip";
+ this.menuStrip.Size = new System.Drawing.Size(329, 25);
+ this.menuStrip.TabIndex = 0;
+ this.menuStrip.Text = "Menu Strip";
+ //
+ // menuItemClose
+ //
+ this.menuItemClose.ForeColor = System.Drawing.Color.WhiteSmoke;
+ this.menuItemClose.Name = "menuItemClose";
+ this.menuItemClose.Size = new System.Drawing.Size(52, 21);
+ this.menuItemClose.Text = "Close";
+ this.menuItemClose.ToolTipText = "Closes the application";
+ this.menuItemClose.Click += new System.EventHandler(this.menuItemClose_Click);
+ //
+ // notifyIcon
+ //
+ this.notifyIcon.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;
+ this.notifyIcon.BalloonTipText = "Hidden!";
+ this.notifyIcon.BalloonTipTitle = "Presentation Obs Scene Switcher";
+ this.notifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon.Icon")));
+ this.notifyIcon.Text = "notifyIcon";
+ this.notifyIcon.Visible = true;
+ this.notifyIcon.DoubleClick += new System.EventHandler(this.notifyIcon_DoubleClick);
+ //
+ // ConfigurationForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(329, 175);
+ this.Controls.Add(this.panel1);
+ this.Controls.Add(this.menuStrip);
+ this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.MainMenuStrip = this.menuStrip;
+ this.Name = "ConfigurationForm";
+ this.Text = "ConfigurationForm";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ConfigurationForm_FormClosing);
+ this.Resize += new System.EventHandler(this.ConfigurationForm_Resize);
+ this.panel1.ResumeLayout(false);
+ this.panel1.PerformLayout();
+ this.menuStrip.ResumeLayout(false);
+ this.menuStrip.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Panel panel1;
+ private System.Windows.Forms.MenuStrip menuStrip;
+ private System.Windows.Forms.ToolStripMenuItem menuItemClose;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.TextBox tbIpAddress;
+ private System.Windows.Forms.TextBox tbPort;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.NotifyIcon notifyIcon;
+ private System.Windows.Forms.Button buttonStart;
+ private System.Windows.Forms.TextBox tbPassword;
+ private System.Windows.Forms.Label label4;
+ }
+}
+
diff --git a/PresentationObsSceneSwitcher/ConfigurationForm.cs b/PresentationObsSceneSwitcher/ConfigurationForm.cs
new file mode 100644
index 0000000..6e618db
--- /dev/null
+++ b/PresentationObsSceneSwitcher/ConfigurationForm.cs
@@ -0,0 +1,72 @@
+using PowerPointToOBSSceneSwitcher.Obs;
+using System;
+using System.Windows.Forms;
+
+namespace PresentationObsSceneSwitcher
+{
+ public partial class ConfigurationForm : Form
+ {
+ #region GUI Behavior fields
+
+ private bool manualClosing;
+ private bool showDisplay;
+
+ #endregion
+
+ private readonly ObsWebSocketClientSettings settings;
+ private ObsWebSocketClient client;
+
+ // TODO: Refactor this Injection
+ public ConfigurationForm(ObsWebSocketClientSettings settings, ObsWebSocketClient client)
+ {
+ InitializeComponent();
+ this.settings = settings ?? new ObsWebSocketClientSettings();
+ this.client = client;
+ }
+
+ #region GUI Behavior events
+
+ protected override void SetVisibleCore(bool value) => base.SetVisibleCore(showDisplay && value);
+
+ private void menuItemClose_Click(object sender, EventArgs e)
+ {
+ this.manualClosing = true;
+ this.notifyIcon.Dispose();
+ this.Close();
+ }
+
+ private void notifyIcon_DoubleClick(object sender, EventArgs e)
+ {
+ this.showDisplay = true;
+ this.Visible = !this.Visible;
+ this.WindowState = FormWindowState.Normal;
+ }
+
+ private void ConfigurationForm_Resize(object sender, EventArgs e)
+ {
+ if (this.WindowState == FormWindowState.Minimized) this.Hide();
+ }
+
+ private void ConfigurationForm_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ if (!manualClosing)
+ {
+ e.Cancel = true;
+ this.Hide();
+ }
+ }
+
+
+ #endregion
+
+ private async void buttonStart_Click(object sender, EventArgs e)
+ {
+ // TODO: Handle the parse better when bindingsource support come.
+ settings.IpAddress = tbIpAddress.Text;
+ settings.Port = int.Parse(tbPort.Text);
+ settings.Password = tbPassword.Text;
+
+ await client.ConnectAsync(settings);
+ }
+ }
+}
diff --git a/PresentationObsSceneSwitcher/ConfigurationForm.resx b/PresentationObsSceneSwitcher/ConfigurationForm.resx
new file mode 100644
index 0000000..5456d88
--- /dev/null
+++ b/PresentationObsSceneSwitcher/ConfigurationForm.resx
@@ -0,0 +1,635 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+
+
+ AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAEAAAOkOAADpDgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEXi8AhF4wA4NeNQaDXjUGg141BoNe
+ NQaDXjUGg141BoNeNQaDXjUGg141BoNeNQaCXTMEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgl0zBINeNQaDXjUGg141BoNeNQaDXjUGg141BoNe
+ NQaDXjUGg141BoNeNQaEXjADhF4vAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAg14wA4Ne
+ MSiDXjRYg140WINeNFiDXjRYg140WINeNFiDXjRYg140WINeNFiDXjRUgl0zNQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIJdMzWDXjRUg140WINe
+ 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
+ Gv8yJhr/MiYa/zMkGis5HBwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAg10yAINd
+ MgqEXTIShF0zFIRdMxSAWjIVTjcjOzgqHP84Khz/OCoc/zkrHOVCMB9nhF0zFIRdMxSEXTMUhF0zFIRd
+ MxSEXTMUhF0zFIRdMxSEXTMUhF0zFIRdMxSEXTMUhF0zFIRdMxSEXTMUhF0zFIRdMxSEXTMUhF0zFIRd
+ MxSEXTMUkGxBFrOXaCPIsH9JyrSEjsq1hNbLtYT5y7WE/8u1hP/LtYT/y7WE/8u1hP/LtYT/y7WE/su1
+ hOPLtYSliXZVmEw9K+s7LR7/OCoc/zgqHP9ONyM7gFoyFYRdMxSEXTMUhF0yEoNdMgqDXTIAAAAAAAAA
+ AACCXDEAglwxDYNdMzWDXTNfg10zeYRdM3+EXTN/g10zf3dVMJRaQSb/WkEm/1pBJv9dQyfxbk4srIRd
+ M3+EXTN/hF0zf4RdM3+EXTN/hF0zf4RdM3+EXTN/hF0zf4RdM3+EXTN/hF0zf4RdM3+EXTN/hF0zf4Rd
+ M3+EXTN/hF0zf4RdM3+EXTN/i2Y8f6KDVYe8oXKxyLCA6cu1hP7LtYT/y7WE/8u1hP/LtYT/y7WE/8u1
+ hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8iygvuijGT+dV9A/2BILP9bQif/d1UwlINdM3+EXTN/hF0zf4Nd
+ M3mDXTNfg10zNIVeMg2FXjIAg18zC4NdMmWDXTPcg10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/iGQ5/519Uf+8o3P/yrSD/8u1hP/LtYT/y7WE/8u1
+ hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8Wtff+khln/jGg9/4Re
+ NP+DXTP/g10z/4NdM/+DXTP/g10z/4NdM9yEXTNkgVo1CoNeM0mDXTP0g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/iWU7/6KDVv/Ap3f/y7WE/8u1
+ hP/LtYT/y7WE/8y2hf/PuIj/0rqM/9S8j//VvpD/1b2Q/9S9j//Tu43/0LmK/8y2hv/LtYT/y7WE/8u1
+ hP/LtYT/ybOC/6yPYf+NaT7/hF40/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z84JbNEiDXTO6g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/iGM4/6OE
+ V//Cqnr/y7WE/8u1hP/LtYT/zLaF/9C5iv/Xv5L/4MWc/+jMpv/t0Kz/79Ov//DTsP/u0a3/6s6o/+LH
+ n//ZwJX/0rqM/8y2hf/LtYT/y7WE/8u1hP/LtIP/q45g/4pmO/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXDS5g10z8oNdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/hmA2/5x7T/++pXX/y7WE/8u1hP/LtYT/zbaG/9W8j//hx5//7dCs//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/79Ku/+XKo//Xv5P/zreI/8u1hP/LtYT/y7WE/8mzgv+jhVf/hmE3/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z8XJRLv9yUS7/clEu/3JRLv9yUS7/clEu/3JRLv9yUS7/clEu/3JR
+ Lv9yUS7/clEu/3JRLv9yUS7/clEu/3JRLv90Ui7/fFgx/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/5FvQ/+2m2z/y7WE/8u1hP/LtYT/zbeH/9e/k//nzKb/79Kv//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/68+r/9zDmP/OuIj/y7WE/8u1
+ hP/LtYT/xK19/5RyRv+EXjT/g10z/4NdM/+DXTP/g10z/4NdM/9EMh//RDIf/0QyH/9EMh//RDIf/0Qy
+ H/9EMh//RDIf/0QyH/9EMh//RDIf/0QyH/9EMh//RDIf/0QyH/9EMh//STUh/2NHKf+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4diOP+lhln/xq9+/8u1hP/LtYT/zLaF/9e/
+ k//ozaf/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/t0a3/28KX/823h//LtYT/y7WE/8u1hP+xlWf/iGQ5/4NdM/+DXTP/g10z/4NdM/+DXTP/Py8e/z8v
+ Hv8/Lx7/Py8e/z8vHv8/Lx7/Py8e/z8vHv8/Lx7/Py8e/z8vHv8/Lx7/Py8e/z8vHv8/Lx7/Py8e/0My
+ H/9dQyf/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+TcUb/uJ5v/8u1
+ hP/LtYT/y7WE/9O8jf/my6P/8NOv//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw/+zPq//WvpD/zLaF/8u1hP/LtYT/yLGB/5Z1SP+EXjT/g10z/4Nd
+ M/+DXTP/g10z/2hKK/9oSiv/aEor/2hKK/9oSiv/aEor/2hKK/9oSiv/aEor/2hKK/9oSiv/aEor/2hK
+ K/9oSiv/aEor/2hKK/9sTSz/elcw/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+FXzX/ooNW/8avf//LtYT/y7WE/863h//exZv/7tGt//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/5Mmi/8+4if/LtYT/y7WE/8u1
+ hP+vk2T/hmE3/4NdM/+DXTP/g10z/4NdM/99WTH/fVkx/31ZMf99WTH/fVkx/31ZMf99WTH/fVkx/31Z
+ Mf99WTH/fVkx/31ZMf99WTH/fVkx/31ZMf99WTH/flox/4JcM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/i2c8/66SY//LtYT/y7WE/8u1hP/UvI//58yl//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw/+7R
+ rv/WvZH/zLaF/8u1hP/LtYT/wqp7/4plO/+DXTP/g10z/4NdM/+DXTP/WUAm/1lAJv9ZQCb/WUAm/1lA
+ Jv9ZQCb/WUAm/1lAJv9ZQCb/WUAm/1lAJv9ZQCb/WUAm/1lAJv9ZQCb/WUAm/11DJ/9vUC3/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/5NxRf+4nm7/y7WE/8u1hP/LtYX/28KX/+3Q
+ rP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsf/w07H/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/4Mad/863h//LtYT/y7WE/8q1g/+TcET/hF40/4NdM/+DXTP/g10z/zIm
+ Gv8yJhr/MiYa/zImGv8yJhr/MiYa/zImGv8yJhr/MiYa/zImGv8yJhr/MiYa/zImGv8yJhr/MiYa/zIm
+ Gv84Khz/WEAl/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+ZeEz/v6Z2/8u1
+ hP/LtYT/zbeH/+DGnf/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//Lavf/1483/9uTQ//Pc
+ wP/w1LP/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw/+jNpv/PuIn/y7WE/8u1hP/LtYT/nn5R/4Rf
+ Nf+DXTP/g10z/4NdM/9VPiX/VT4l/1U+Jf9VPiX/VT4l/1U+Jf9VPiX/VT4l/1U+Jf9VPiX/VT4l/1U+
+ Jf9VPiX/VT4l/1U+Jf9VPiX/WUAm/21OLP+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/nXxQ/8Ore//LtYT/y7WE/9C5iv/jyKD/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//HW
+ tv/469v//vv5///+/P/68eX/8tq8//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/t0a3/0LmK/8u1
+ hP/LtYT/y7WE/6aIWv+FXzX/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/55+Uf/FrX3/y7WE/8u1hP/Ruov/5Mmi//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/z3L//+/Xs//////////////38//Tfxf/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/79Ow/9C5iv/LtYT/y7WE/8u1hP+oi17/hWA1/4NdM/+DXTP/g10z/2hLK/9oSyv/aEsr/2hL
+ K/9oSyv/aEsr/2hLK/9oSyv/aEsr/2hLK/9oSyv/aEsr/2hLK/9oSyv/aEsr/2hLK/9rTSz/eFYw/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+efVH/xKx8/8u1hP/LtYT/0bmK/+TJ
+ of/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8tm7//rx5v///v3///////348v/z3cL/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw/+7Rrv/QuYr/y7WE/8u1hP/LtYT/p4lc/4VgNf+DXTP/g10z/4Nd
+ M/8+Lh7/Pi4e/z4uHv8+Lh7/Pi4e/z4uHv8+Lh7/Pi4e/z4uHv8+Lh7/Pi4e/z4uHv8+Lh7/Pi4e/z4u
+ Hv89Lh7/QjEf/19EKP+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/m3pO/8Go
+ ef/LtYT/y7WE/864iP/ix5//8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DUsf/14cn/+e7g//rv
+ 4//25M//8da2//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/rzqn/z7iJ/8u1hP/LtYT/y7WE/6KC
+ Vv+FXzX/g10z/4NdM/+DXTP/RTIg/0UyIP9FMiD/RTIg/0UyIP9FMiD/RTIg/0UyIP9FMiD/RTIg/0Uy
+ IP9FMiD/RTIg/0UyIP9FMiD/RTIg/0o2If9jRyn/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/5Z0SP+7oXL/y7WE/8u1hP/MtoX/3sSa/+/Srv/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NSx//LYuv/y2bv/8dSz//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/5Mmh/864
+ iP/LtYT/y7WE/8u1hP+Yd0r/hF40/4NdM/+DXTP/g10z/25OLf9uTi3/bk4t/25OLf9uTi3/bk4t/25O
+ Lf9uTi3/bk4t/25OLf9uTi3/bk4t/25OLf9uTi3/bk4t/25OLf9xUS7/fVgx/4NdM/+DXTP/g10z/4Ff
+ Nv96ZkT/dmlK/39hOv+DXTP/g10z/4NdM/+Pa0H/spdp/8u1hP/LtYT/y7WE/9i/k//qzqn/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw/9rBlv/Ntob/y7WE/8u1hP/HsID/jWk+/4NdM/+DXTP/g10z/4NdM/93VS//d1Uv/3dV
+ L/93VS//d1Uv/3dVL/93VS//d1Uv/3dVL/93VS//d1Uv/3dVL/93VS//d1Uv/3dVL/94VS//elcx/4Fb
+ M/+DXTP/g10z/39hOv9oeGP/RZqi/0Ceqv9Zhn7/e2VC/4NdM/+DXTP/h2I3/6eJXP/Js4L/y7WE/8u1
+ hP/QuYr/4sig/+/Sr//w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw/+rOqf/Suoz/y7WE/8u1hP/LtYT/uJ5v/4diN/+DXTP/g10z/4Nd
+ M/+DXTP/TTgi/004Iv9NOCL/TTgi/004Iv9NOCL/TTgi/004Iv9NOCL/TTgi/004Iv9NOCL/TTgi/004
+ Iv9NOCL/TTki/1I8JP9oSyv/g10z/4NdM/90bE7/QZ2o/xrD7f8aw+//L6/J/2R7a/+DXTP/g10z/4Nd
+ M/+aeU3/v6Z3/8u1hP/LtYT/y7WE/9e/k//qzqn/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw/+/Srv/cwpj/zbeG/8u1hP/LtYT/y7SE/6CA
+ VP+FXzX/g10z/4NdM/+DXTP/g10z/zImGv8yJhr/MiYa/zImGv8yJhr/MiYa/zImGv8yJhr/MiYa/zIm
+ Gv8yJhr/MiYa/zImGv8yJhr/MiYa/zImGv85Khz/WkEn/4NdM/+DXTP/b3FX/zWovv8ZxPD/GcTw/ye3
+ 2P9Zhn7/g10z/4NdM/+DXTP/i2c8/62RY//Js4L/y7WE/8u1hP/OuIj/3cSa/+zQq//w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/iyKD/0LmK/8u1
+ hP/LtYT/y7WE/72jdP+NaT7/g10z/4NdM/+DXTP/g10z/4NdM/9gRSj/YEUo/2BFKP9gRSj/YEUo/2BF
+ KP9gRSj/YEUo/2BFKP9gRSj/YEUo/2BFKP9gRSj/YEUo/2BFKP9gRSj/ZEgp/3NSLv+DXTP/g10z/3ln
+ Rf9OkJL/IL3j/x3A6f86pLb/bXNb/4NdM/+DXTP/g10z/4ReNP+aeUz/vqV1/8u1hP/LtYT/y7WE/9C5
+ iv/fxZz/7NCs//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw/+/S
+ r//kyaL/0ruN/8y2hf/LtYT/y7WE/8qzgv+gf1L/hWA1/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z+YNd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+CXjb/dGxO/1uEe/9XiIL/anVf/4BgOf+DXTP/g10z/4NdM/+DXTP/iWU6/6eJ
+ W//FrX3/y7WE/8u1hP/LtYT/0LmK/9zDmP/pzqj/79Kv//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw/+zQrP/gxp3/0ruN/8y2hf/LtYT/y7WE/8u1hP+zmGn/i2Y7/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z+YNdM9eDXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+CXjX/gV82/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+Oaj//r5Jk/8ixgP/LtYT/y7WE/8u1hP/OuIj/1r6R/+DGnf/pzaf/79Ku//DT
+ sP/w07D/8NOw//DTsP/w07D/686q/+PIoP/ZwJT/z7mJ/8u1hf/LtYT/y7WE/8u1hP+5oHD/k3FF/4Re
+ NP+DXTP/g10z/4NdM/+DXTP/g10z/4NdMtWCXTN6g10z/oNdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/hF40/5JvRP+yl2j/yLGA/8u1hP/LtYT/y7WE/8u1
+ hP/PuIn/1b2P/9rBlv/exJr/4Mad/+DGnf/exZv/28KX/9a+kf/Ruov/zLaF/8u1hP/LtYT/y7WE/8u1
+ hP+7onP/mHZK/4VfNf+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/6DXTJ4gV40HYNdM6WDXTP8g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+FXzX/kW9D/66R
+ Y//FrX3/y7WE/8u1hP/LtYT/y7WE/8u1hP/MtoX/zreH/8+4if/PuIn/zriH/8y2hf/LtYT/y7WE/8u1
+ hP/LtYT/y7WE/8u0g/+3nG3/mHZK/4VgNv+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/uDXTOkg1wyHYNe
+ MwGDXjMpglwzcYNdM6iEXTO7hF00vYRdNL2EXTS9hF00vYRdNL2EXTS9hF00vYRdNL2EXTS9hF00vYRd
+ NL2EXTS9hF00vYRdNL2EXTS9hF00vYRdNL2EXTS9hF00vYRdNL2EXTS9hF00vYRdNL2EXTS9hF00vYRd
+ NL2EXTS9hF00vYVeNb2RbkS9rI9hzMKqeuvKtIP8y7WE/8u1hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8u1
+ hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8WuffOzmGnSmXdLv4ZgNr2EXTS9hF00vYRdNL2EXTS9hF0zu4Nd
+ M6iDXTRwg10yKINdMgEAAAAAgFo1AIFaNQ2EXTQphFwzM4RdNDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRd
+ NDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRd
+ NDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRdNDSEXTQ0hF42NJt7Tzy+pHRQy7SDiMu1hNHLtYT4y7WE/8u1
+ hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8u1hP/LtYT/y7WE4cu1hJrDq3paooJWP4hiOTWEXTQ0hF00NIRd
+ NDSEXTQ0hF00NIRcMzOEXTQpg102DINdNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1b+AAs22
+ hBnMtIU9y7WEaMu1hJXLtYS4y7WE0su1hN7LtYTey7WE1su1hMDLtYSfy7WFc8u1hEnKtoQhyraEBQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADV1VUC5uBWG+jiViDq6lUEAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA/4CAAMuzhAvKtYUey7aELsq1hDrLtYQ/y7WFP8u1hDzLtYUyzLWFI8q2
+ hg/Ht4cCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObgVxnm4lgj5uJYAwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5+BYJefg
+ V4vn4Fez5+FXWOTkWwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObgWDLn4Fet5+BXwebe
+ ViLm3VUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAObhWCLn4Fec5+BX9ufgV9Dn4Vdp6N9XEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAefh
+ WErn4Fe+5+BX+OfgV+Hl31ge495aAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD//4AB5uZeCeTkWwzm4lgH5+BWPOfgV67n4Ff25+BX3+fgV5Dm4Vcu399gAwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA6uNVFubfVnnn4FfQ5+BX+ufgWNfm4FhR5OBaB9/fYAbr4FwS6+BcAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6OBWK+fgV5Ln4Feg5t9WPeniWQjm31Yy5+BXmefg
+ V+3n4Ffu5+BXwufgV3Tm3lci1dVVAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAADj41UQ5+BXWufgV7Xn4Ffo5+BX/OfgV7jm4FhD5OBZCePjVRPn4FeX5+BXw+fe
+ VS7n3lUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOfhVzTn4Fe25+BX9Ofg
+ V7nn4VdJ4t5aCOfgWB/n4Fds5+BXz+fgV/jn4Ffn5+BWxOfgVonn4FdF6uJVEv//QAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA399QCebgVjTn4Fd25+BXuefgV9/n4Ff55+BX6efgV4Tn4Fcs5eBaBefh
+ VR3n4Fen5+BX8OfgV/no4Vc16OFWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AADo4lUL5+BXUefgV8bn4Ff35+BXzefgV2no4lcS6OBXD+jhVzjn4VeG5+BX2+fgV/rn4Ffu5+BX2+fg
+ V8fn4Vem5uBXhebhWG/n4Vhh5uBXYOfgVmnn31h+5+BXnOfgV8Hn4FfW5+BX6efgV/rn4Ffu5+BXoObg
+ V0Tn4FgV5+BYAufhV0Ln4Fe85+BX9efgV/bn31dz6OFXDejiVwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA//8AAOffVwvo4FdK5+BXvOfgV/nn4Ffj5+BXl+ffVzLh3VYG5+FXFObh
+ Vzbn4FZz5+BXvefgV/Dn4Ff+5+BX9ufgV+7n4Ffo5+BX5efgV+Tn4Ffn5+BX7OfgV/Tn4Ff85+BX++ff
+ V83n31eI5t9XQObgVhzl4FkF599YFujgV37n4FfW5+BX+ufgV+bo31he5t5XEebeVwAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6OFXCefhVzPn4FeZ5+BX8Ofg
+ V/Ln31fM5uBXfejgWCbu2lwF5+BWD+fgVyDo4Fc35+BXYefgWIro4Fiq599XwOfgV8zn4FfL5+BWxOjh
+ V7Hn4FeV599WbObgWD/n31cl6N9XFOTdVwTr4FwR5+BXYufgV8Hn4Ffs5+BX/effWL/o31c/6d5YC+ne
+ WQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AADn4lcE6OJXG+fgV2Tn4FfL5+BX+efgV+7n4FfP5+BXj+ffWEHm31kO6t9VAufhWArn4FgT6OBYGeff
+ Vx7n4Fch5+BXIOfgVh/o4Vcb5+BWFebfVg3k3lkD/PxDA+bfWTHn4Fd55+BXxefgV+fn4Ff75+BX6Ofg
+ V33n31gk695WBe7dVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAOrqVQHn4FcL5t9WLufgV33n4FfX5+BX++fgV/Ln4Ffk5+BXx+jg
+ WJfo4Fdl5+FVP+jgVR/o4lEM5uZNAwAAAADf31AK6OJUGufgVzbn4FZZ5uFXiefgV77n4Ffe5+BX7ufg
+ V/zn4Fbt5+FXmefhVjfm4FYQ5uBWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOXeVQPn4FcO5t9XKufg
+ WGvn4Fe/5+BX8ufgV/zn4Ff05+BX7OfgV+bn4Ffh5+BX3ufgV9zn4Ffc5+BX3efgV+Dn4Ffk5+BX6ufg
+ V/Ln4Ff75+BX/OfgV8/n31iD5t9VMubhVxPn41QD5uZNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAOXcWALo31gK5+BXFufgVjfn4FZt599XpefgV9Tn4Ff05+BX/ufgV//n4Ff/5+BX/+fg
+ V//n4Ff/5+BX+ufgV9/m4Fez5uFYfejgV0Dn4Fcc599YDuTeVAPb20kAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADm4VUD5+BWCuffVxDn4FcW5d9VHujh
+ VjLn4VZE5+BXUejgWFHm4FZJ5eFWOefhVSLn4FYY5uBXEubhWAvo4FYE6t9VAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAANvbSQDp4lQC5+JVBOfgVwbo4FgG5t9WBePhVQPm5k0B//8AAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA//////////////////////////////////////////////////////gAf////gAf8AB////+
+ AA/wAH////4AD/AAf////gAP8AB////+AA/4AH////4AH/wA/////wA//gP///8AQH/+A///+AAAf+AA
+ AAAAAAAHgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAP/////8AAP////
+ //D+AD+P////8H///wf////wP//8B////4AP//gB////gAP/4AD///+AAH8AAP///4AAAAAB////wAAA
+ AAP////gAAAAB/////AAAAAP////+AAIAB/////+AAAAf/////+AAAH///////AAD////////4D/////
+ //////////////////////////////////////////////////8=
+
+
+
+
+ AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAEAAAOkOAADpDgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ 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
+ MxSEXTMUhF0zFIRdMxSEXTMUhF0zFIRdMxSEXTMUhF0zFIRdMxSEXTMUhF0zFIRdMxSEXTMUhF0zFIRd
+ MxSEXTMUkGxBFrOXaCPIsH9JyrSEjsq1hNbLtYT5y7WE/8u1hP/LtYT/y7WE/8u1hP/LtYT/y7WE/su1
+ hOPLtYSliXZVmEw9K+s7LR7/OCoc/zgqHP9ONyM7gFoyFYRdMxSEXTMUhF0yEoNdMgqDXTIAAAAAAAAA
+ AACCXDEAglwxDYNdMzWDXTNfg10zeYRdM3+EXTN/g10zf3dVMJRaQSb/WkEm/1pBJv9dQyfxbk4srIRd
+ M3+EXTN/hF0zf4RdM3+EXTN/hF0zf4RdM3+EXTN/hF0zf4RdM3+EXTN/hF0zf4RdM3+EXTN/hF0zf4Rd
+ M3+EXTN/hF0zf4RdM3+EXTN/i2Y8f6KDVYe8oXKxyLCA6cu1hP7LtYT/y7WE/8u1hP/LtYT/y7WE/8u1
+ hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8iygvuijGT+dV9A/2BILP9bQif/d1UwlINdM3+EXTN/hF0zf4Nd
+ M3mDXTNfg10zNIVeMg2FXjIAg18zC4NdMmWDXTPcg10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/iGQ5/519Uf+8o3P/yrSD/8u1hP/LtYT/y7WE/8u1
+ hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8Wtff+khln/jGg9/4Re
+ NP+DXTP/g10z/4NdM/+DXTP/g10z/4NdM9yEXTNkgVo1CoNeM0mDXTP0g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/iWU7/6KDVv/Ap3f/y7WE/8u1
+ hP/LtYT/y7WE/8y2hf/PuIj/0rqM/9S8j//VvpD/1b2Q/9S9j//Tu43/0LmK/8y2hv/LtYT/y7WE/8u1
+ hP/LtYT/ybOC/6yPYf+NaT7/hF40/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z84JbNEiDXTO6g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/iGM4/6OE
+ V//Cqnr/y7WE/8u1hP/LtYT/zLaF/9C5iv/Xv5L/4MWc/+jMpv/t0Kz/79Ov//DTsP/u0a3/6s6o/+LH
+ n//ZwJX/0rqM/8y2hf/LtYT/y7WE/8u1hP/LtIP/q45g/4pmO/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXDS5g10z8oNdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/hmA2/5x7T/++pXX/y7WE/8u1hP/LtYT/zbaG/9W8j//hx5//7dCs//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/79Ku/+XKo//Xv5P/zreI/8u1hP/LtYT/y7WE/8mzgv+jhVf/hmE3/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z8XJRLv9yUS7/clEu/3JRLv9yUS7/clEu/3JRLv9yUS7/clEu/3JR
+ Lv9yUS7/clEu/3JRLv9yUS7/clEu/3JRLv90Ui7/fFgx/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/5FvQ/+2m2z/y7WE/8u1hP/LtYT/zbeH/9e/k//nzKb/79Kv//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/68+r/9zDmP/OuIj/y7WE/8u1
+ hP/LtYT/xK19/5RyRv+EXjT/g10z/4NdM/+DXTP/g10z/4NdM/9EMh//RDIf/0QyH/9EMh//RDIf/0Qy
+ H/9EMh//RDIf/0QyH/9EMh//RDIf/0QyH/9EMh//RDIf/0QyH/9EMh//STUh/2NHKf+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4diOP+lhln/xq9+/8u1hP/LtYT/zLaF/9e/
+ k//ozaf/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/t0a3/28KX/823h//LtYT/y7WE/8u1hP+xlWf/iGQ5/4NdM/+DXTP/g10z/4NdM/+DXTP/Py8e/z8v
+ Hv8/Lx7/Py8e/z8vHv8/Lx7/Py8e/z8vHv8/Lx7/Py8e/z8vHv8/Lx7/Py8e/z8vHv8/Lx7/Py8e/0My
+ H/9dQyf/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+TcUb/uJ5v/8u1
+ hP/LtYT/y7WE/9O8jf/my6P/8NOv//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw/+zPq//WvpD/zLaF/8u1hP/LtYT/yLGB/5Z1SP+EXjT/g10z/4Nd
+ M/+DXTP/g10z/2hKK/9oSiv/aEor/2hKK/9oSiv/aEor/2hKK/9oSiv/aEor/2hKK/9oSiv/aEor/2hK
+ K/9oSiv/aEor/2hKK/9sTSz/elcw/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+FXzX/ooNW/8avf//LtYT/y7WE/863h//exZv/7tGt//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/5Mmi/8+4if/LtYT/y7WE/8u1
+ hP+vk2T/hmE3/4NdM/+DXTP/g10z/4NdM/99WTH/fVkx/31ZMf99WTH/fVkx/31ZMf99WTH/fVkx/31Z
+ Mf99WTH/fVkx/31ZMf99WTH/fVkx/31ZMf99WTH/flox/4JcM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/i2c8/66SY//LtYT/y7WE/8u1hP/UvI//58yl//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw/+7R
+ rv/WvZH/zLaF/8u1hP/LtYT/wqp7/4plO/+DXTP/g10z/4NdM/+DXTP/WUAm/1lAJv9ZQCb/WUAm/1lA
+ Jv9ZQCb/WUAm/1lAJv9ZQCb/WUAm/1lAJv9ZQCb/WUAm/1lAJv9ZQCb/WUAm/11DJ/9vUC3/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/5NxRf+4nm7/y7WE/8u1hP/LtYX/28KX/+3Q
+ rP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsf/w07H/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/4Mad/863h//LtYT/y7WE/8q1g/+TcET/hF40/4NdM/+DXTP/g10z/zIm
+ Gv8yJhr/MiYa/zImGv8yJhr/MiYa/zImGv8yJhr/MiYa/zImGv8yJhr/MiYa/zImGv8yJhr/MiYa/zIm
+ Gv84Khz/WEAl/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+ZeEz/v6Z2/8u1
+ hP/LtYT/zbeH/+DGnf/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//Lavf/1483/9uTQ//Pc
+ wP/w1LP/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw/+jNpv/PuIn/y7WE/8u1hP/LtYT/nn5R/4Rf
+ Nf+DXTP/g10z/4NdM/9VPiX/VT4l/1U+Jf9VPiX/VT4l/1U+Jf9VPiX/VT4l/1U+Jf9VPiX/VT4l/1U+
+ Jf9VPiX/VT4l/1U+Jf9VPiX/WUAm/21OLP+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/nXxQ/8Ore//LtYT/y7WE/9C5iv/jyKD/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//HW
+ tv/469v//vv5///+/P/68eX/8tq8//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/t0a3/0LmK/8u1
+ hP/LtYT/y7WE/6aIWv+FXzX/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/55+Uf/FrX3/y7WE/8u1hP/Ruov/5Mmi//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/z3L//+/Xs//////////////38//Tfxf/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/79Ow/9C5iv/LtYT/y7WE/8u1hP+oi17/hWA1/4NdM/+DXTP/g10z/2hLK/9oSyv/aEsr/2hL
+ K/9oSyv/aEsr/2hLK/9oSyv/aEsr/2hLK/9oSyv/aEsr/2hLK/9oSyv/aEsr/2hLK/9rTSz/eFYw/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+efVH/xKx8/8u1hP/LtYT/0bmK/+TJ
+ of/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8tm7//rx5v///v3///////348v/z3cL/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw/+7Rrv/QuYr/y7WE/8u1hP/LtYT/p4lc/4VgNf+DXTP/g10z/4Nd
+ M/8+Lh7/Pi4e/z4uHv8+Lh7/Pi4e/z4uHv8+Lh7/Pi4e/z4uHv8+Lh7/Pi4e/z4uHv8+Lh7/Pi4e/z4u
+ Hv89Lh7/QjEf/19EKP+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/m3pO/8Go
+ ef/LtYT/y7WE/864iP/ix5//8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DUsf/14cn/+e7g//rv
+ 4//25M//8da2//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/rzqn/z7iJ/8u1hP/LtYT/y7WE/6KC
+ Vv+FXzX/g10z/4NdM/+DXTP/RTIg/0UyIP9FMiD/RTIg/0UyIP9FMiD/RTIg/0UyIP9FMiD/RTIg/0Uy
+ IP9FMiD/RTIg/0UyIP9FMiD/RTIg/0o2If9jRyn/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/5Z0SP+7oXL/y7WE/8u1hP/MtoX/3sSa/+/Srv/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NSx//LYuv/y2bv/8dSz//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/5Mmh/864
+ iP/LtYT/y7WE/8u1hP+Yd0r/hF40/4NdM/+DXTP/g10z/25OLf9uTi3/bk4t/25OLf9uTi3/bk4t/25O
+ Lf9uTi3/bk4t/25OLf9uTi3/bk4t/25OLf9uTi3/bk4t/25OLf9xUS7/fVgx/4NdM/+DXTP/g10z/4Ff
+ Nv96ZkT/dmlK/39hOv+DXTP/g10z/4NdM/+Pa0H/spdp/8u1hP/LtYT/y7WE/9i/k//qzqn/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw/9rBlv/Ntob/y7WE/8u1hP/HsID/jWk+/4NdM/+DXTP/g10z/4NdM/93VS//d1Uv/3dV
+ L/93VS//d1Uv/3dVL/93VS//d1Uv/3dVL/93VS//d1Uv/3dVL/93VS//d1Uv/3dVL/94VS//elcx/4Fb
+ M/+DXTP/g10z/39hOv9oeGP/RZqi/0Ceqv9Zhn7/e2VC/4NdM/+DXTP/h2I3/6eJXP/Js4L/y7WE/8u1
+ hP/QuYr/4sig/+/Sr//w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw/+rOqf/Suoz/y7WE/8u1hP/LtYT/uJ5v/4diN/+DXTP/g10z/4Nd
+ M/+DXTP/TTgi/004Iv9NOCL/TTgi/004Iv9NOCL/TTgi/004Iv9NOCL/TTgi/004Iv9NOCL/TTgi/004
+ Iv9NOCL/TTki/1I8JP9oSyv/g10z/4NdM/90bE7/QZ2o/xrD7f8aw+//L6/J/2R7a/+DXTP/g10z/4Nd
+ M/+aeU3/v6Z3/8u1hP/LtYT/y7WE/9e/k//qzqn/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw/+/Srv/cwpj/zbeG/8u1hP/LtYT/y7SE/6CA
+ VP+FXzX/g10z/4NdM/+DXTP/g10z/zImGv8yJhr/MiYa/zImGv8yJhr/MiYa/zImGv8yJhr/MiYa/zIm
+ Gv8yJhr/MiYa/zImGv8yJhr/MiYa/zImGv85Khz/WkEn/4NdM/+DXTP/b3FX/zWovv8ZxPD/GcTw/ye3
+ 2P9Zhn7/g10z/4NdM/+DXTP/i2c8/62RY//Js4L/y7WE/8u1hP/OuIj/3cSa/+zQq//w07D/8NOw//DT
+ sP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/iyKD/0LmK/8u1
+ hP/LtYT/y7WE/72jdP+NaT7/g10z/4NdM/+DXTP/g10z/4NdM/9gRSj/YEUo/2BFKP9gRSj/YEUo/2BF
+ KP9gRSj/YEUo/2BFKP9gRSj/YEUo/2BFKP9gRSj/YEUo/2BFKP9gRSj/ZEgp/3NSLv+DXTP/g10z/3ln
+ Rf9OkJL/IL3j/x3A6f86pLb/bXNb/4NdM/+DXTP/g10z/4ReNP+aeUz/vqV1/8u1hP/LtYT/y7WE/9C5
+ iv/fxZz/7NCs//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DTsP/w07D/8NOw/+/S
+ r//kyaL/0ruN/8y2hf/LtYT/y7WE/8qzgv+gf1L/hWA1/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z+YNd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+CXjb/dGxO/1uEe/9XiIL/anVf/4BgOf+DXTP/g10z/4NdM/+DXTP/iWU6/6eJ
+ W//FrX3/y7WE/8u1hP/LtYT/0LmK/9zDmP/pzqj/79Kv//DTsP/w07D/8NOw//DTsP/w07D/8NOw//DT
+ sP/w07D/8NOw/+zQrP/gxp3/0ruN/8y2hf/LtYT/y7WE/8u1hP+zmGn/i2Y7/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z+YNdM9eDXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+CXjX/gV82/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+Oaj//r5Jk/8ixgP/LtYT/y7WE/8u1hP/OuIj/1r6R/+DGnf/pzaf/79Ku//DT
+ sP/w07D/8NOw//DTsP/w07D/686q/+PIoP/ZwJT/z7mJ/8u1hf/LtYT/y7WE/8u1hP+5oHD/k3FF/4Re
+ NP+DXTP/g10z/4NdM/+DXTP/g10z/4NdMtWCXTN6g10z/oNdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/hF40/5JvRP+yl2j/yLGA/8u1hP/LtYT/y7WE/8u1
+ hP/PuIn/1b2P/9rBlv/exJr/4Mad/+DGnf/exZv/28KX/9a+kf/Ruov/zLaF/8u1hP/LtYT/y7WE/8u1
+ hP+7onP/mHZK/4VfNf+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/6DXTJ4gV40HYNdM6WDXTP8g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4Nd
+ M/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/+FXzX/kW9D/66R
+ Y//FrX3/y7WE/8u1hP/LtYT/y7WE/8u1hP/MtoX/zreH/8+4if/PuIn/zriH/8y2hf/LtYT/y7WE/8u1
+ hP/LtYT/y7WE/8u0g/+3nG3/mHZK/4VgNv+DXTP/g10z/4NdM/+DXTP/g10z/4NdM/uDXTOkg1wyHYNe
+ MwGDXjMpglwzcYNdM6iEXTO7hF00vYRdNL2EXTS9hF00vYRdNL2EXTS9hF00vYRdNL2EXTS9hF00vYRd
+ NL2EXTS9hF00vYRdNL2EXTS9hF00vYRdNL2EXTS9hF00vYRdNL2EXTS9hF00vYRdNL2EXTS9hF00vYRd
+ NL2EXTS9hF00vYVeNb2RbkS9rI9hzMKqeuvKtIP8y7WE/8u1hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8u1
+ hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8WuffOzmGnSmXdLv4ZgNr2EXTS9hF00vYRdNL2EXTS9hF0zu4Nd
+ M6iDXTRwg10yKINdMgEAAAAAgFo1AIFaNQ2EXTQphFwzM4RdNDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRd
+ NDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRd
+ NDSEXTQ0hF00NIRdNDSEXTQ0hF00NIRdNDSEXTQ0hF42NJt7Tzy+pHRQy7SDiMu1hNHLtYT4y7WE/8u1
+ hP/LtYT/y7WE/8u1hP/LtYT/y7WE/8u1hP/LtYT/y7WE4cu1hJrDq3paooJWP4hiOTWEXTQ0hF00NIRd
+ NDSEXTQ0hF00NIRcMzOEXTQpg102DINdNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1b+AAs22
+ hBnMtIU9y7WEaMu1hJXLtYS4y7WE0su1hN7LtYTey7WE1su1hMDLtYSfy7WFc8u1hEnKtoQhyraEBQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADV1VUC5uBWG+jiViDq6lUEAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA/4CAAMuzhAvKtYUey7aELsq1hDrLtYQ/y7WFP8u1hDzLtYUyzLWFI8q2
+ hg/Ht4cCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObgVxnm4lgj5uJYAwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5+BYJefg
+ V4vn4Fez5+FXWOTkWwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObgWDLn4Fet5+BXwebe
+ ViLm3VUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAObhWCLn4Fec5+BX9ufgV9Dn4Vdp6N9XEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAefh
+ WErn4Fe+5+BX+OfgV+Hl31ge495aAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD//4AB5uZeCeTkWwzm4lgH5+BWPOfgV67n4Ff25+BX3+fgV5Dm4Vcu399gAwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA6uNVFubfVnnn4FfQ5+BX+ufgWNfm4FhR5OBaB9/fYAbr4FwS6+BcAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6OBWK+fgV5Ln4Feg5t9WPeniWQjm31Yy5+BXmefg
+ V+3n4Ffu5+BXwufgV3Tm3lci1dVVAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAADj41UQ5+BXWufgV7Xn4Ffo5+BX/OfgV7jm4FhD5OBZCePjVRPn4FeX5+BXw+fe
+ VS7n3lUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOfhVzTn4Fe25+BX9Ofg
+ V7nn4VdJ4t5aCOfgWB/n4Fds5+BXz+fgV/jn4Ffn5+BWxOfgVonn4FdF6uJVEv//QAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA399QCebgVjTn4Fd25+BXuefgV9/n4Ff55+BX6efgV4Tn4Fcs5eBaBefh
+ VR3n4Fen5+BX8OfgV/no4Vc16OFWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AADo4lUL5+BXUefgV8bn4Ff35+BXzefgV2no4lcS6OBXD+jhVzjn4VeG5+BX2+fgV/rn4Ffu5+BX2+fg
+ V8fn4Vem5uBXhebhWG/n4Vhh5uBXYOfgVmnn31h+5+BXnOfgV8Hn4FfW5+BX6efgV/rn4Ffu5+BXoObg
+ V0Tn4FgV5+BYAufhV0Ln4Fe85+BX9efgV/bn31dz6OFXDejiVwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA//8AAOffVwvo4FdK5+BXvOfgV/nn4Ffj5+BXl+ffVzLh3VYG5+FXFObh
+ Vzbn4FZz5+BXvefgV/Dn4Ff+5+BX9ufgV+7n4Ffo5+BX5efgV+Tn4Ffn5+BX7OfgV/Tn4Ff85+BX++ff
+ V83n31eI5t9XQObgVhzl4FkF599YFujgV37n4FfW5+BX+ufgV+bo31he5t5XEebeVwAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6OFXCefhVzPn4FeZ5+BX8Ofg
+ V/Ln31fM5uBXfejgWCbu2lwF5+BWD+fgVyDo4Fc35+BXYefgWIro4Fiq599XwOfgV8zn4FfL5+BWxOjh
+ V7Hn4FeV599WbObgWD/n31cl6N9XFOTdVwTr4FwR5+BXYufgV8Hn4Ffs5+BX/effWL/o31c/6d5YC+ne
+ WQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AADn4lcE6OJXG+fgV2Tn4FfL5+BX+efgV+7n4FfP5+BXj+ffWEHm31kO6t9VAufhWArn4FgT6OBYGeff
+ Vx7n4Fch5+BXIOfgVh/o4Vcb5+BWFebfVg3k3lkD/PxDA+bfWTHn4Fd55+BXxefgV+fn4Ff75+BX6Ofg
+ V33n31gk695WBe7dVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAOrqVQHn4FcL5t9WLufgV33n4FfX5+BX++fgV/Ln4Ffk5+BXx+jg
+ WJfo4Fdl5+FVP+jgVR/o4lEM5uZNAwAAAADf31AK6OJUGufgVzbn4FZZ5uFXiefgV77n4Ffe5+BX7ufg
+ V/zn4Fbt5+FXmefhVjfm4FYQ5uBWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOXeVQPn4FcO5t9XKufg
+ WGvn4Fe/5+BX8ufgV/zn4Ff05+BX7OfgV+bn4Ffh5+BX3ufgV9zn4Ffc5+BX3efgV+Dn4Ffk5+BX6ufg
+ V/Ln4Ff75+BX/OfgV8/n31iD5t9VMubhVxPn41QD5uZNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAOXcWALo31gK5+BXFufgVjfn4FZt599XpefgV9Tn4Ff05+BX/ufgV//n4Ff/5+BX/+fg
+ V//n4Ff/5+BX+ufgV9/m4Fez5uFYfejgV0Dn4Fcc599YDuTeVAPb20kAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADm4VUD5+BWCuffVxDn4FcW5d9VHujh
+ VjLn4VZE5+BXUejgWFHm4FZJ5eFWOefhVSLn4FYY5uBXEubhWAvo4FYE6t9VAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAANvbSQDp4lQC5+JVBOfgVwbo4FgG5t9WBePhVQPm5k0B//8AAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA//////////////////////////////////////////////////////gAf////gAf8AB////+
+ AA/wAH////4AD/AAf////gAP8AB////+AA/4AH////4AH/wA/////wA//gP///8AQH/+A///+AAAf+AA
+ AAAAAAAHgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAP/////8AAP////
+ //D+AD+P////8H///wf////wP//8B////4AP//gB////gAP/4AD///+AAH8AAP///4AAAAAB////wAAA
+ AAP////gAAAAB/////AAAAAP////+AAIAB/////+AAAAf/////+AAAH///////AAD////////4D/////
+ //////////////////////////////////////////////////8=
+
+
+
\ No newline at end of file
diff --git a/PresentationObsSceneSwitcher/IPresentationSubscriber.cs b/PresentationObsSceneSwitcher/IPresentationSubscriber.cs
new file mode 100644
index 0000000..7cf38e8
--- /dev/null
+++ b/PresentationObsSceneSwitcher/IPresentationSubscriber.cs
@@ -0,0 +1,18 @@
+using System.Threading.Tasks;
+
+namespace PresentationObsSceneSwitcher
+{
+ ///
+ /// Receives the name of the OBS scene.
+ ///
+ ///
+ public delegate Task PresentationSuscription(string scene);
+
+ ///
+ /// Manages the suscriptions to a Presetation
+ ///
+ public interface IPresentationSubscriber
+ {
+ bool Subscribe(string appName, PresentationSuscription suscription);
+ }
+}
diff --git a/PresentationObsSceneSwitcher/JsonSettingsRepository.cs b/PresentationObsSceneSwitcher/JsonSettingsRepository.cs
new file mode 100644
index 0000000..cf045a0
--- /dev/null
+++ b/PresentationObsSceneSwitcher/JsonSettingsRepository.cs
@@ -0,0 +1,30 @@
+using Newtonsoft.Json;
+using PowerPointToOBSSceneSwitcher.Obs;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace PresentationObsSceneSwitcher
+{
+ public class JsonSettingsRepository
+ {
+ public async Task SaveAsync(ObsWebSocketClientSettings settings)
+ {
+ string json = JsonConvert.SerializeObject(settings);
+ await File.WriteAllTextAsync(@".\settings.json", json).ConfigureAwait(false); // Maybe AppData is a better location, but...
+ }
+
+ public async Task LoadAsync()
+ {
+ try
+ {
+ string json = await File.ReadAllTextAsync(@".\settings.json").ConfigureAwait(false);
+
+ return JsonConvert.DeserializeObject(json);
+ }
+ catch (FileNotFoundException ex)
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/PresentationObsSceneSwitcher/Obs/ObsWebSocketClient.cs b/PresentationObsSceneSwitcher/Obs/ObsWebSocketClient.cs
new file mode 100644
index 0000000..059f7a4
--- /dev/null
+++ b/PresentationObsSceneSwitcher/Obs/ObsWebSocketClient.cs
@@ -0,0 +1,168 @@
+using OBS.WebSocket.NET;
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Net;
+using System.Threading.Tasks;
+
+namespace PowerPointToOBSSceneSwitcher.Obs
+{
+ ///
+ /// Defines all the settings a ObsWebSocketClient needs
+ ///
+ /// Configuring the ObsWebSocketClient with a Settings object allows to use it with DI
+ public class ObsWebSocketClientSettings
+ {
+ private string ipAddress = "127.0.0.1";
+
+ ///
+ /// Ip address of the obs websocket server
+ ///
+ public string IpAddress
+ {
+ get => ipAddress;
+ set => this.ipAddress = IPAddress.TryParse(value, out _) ? value
+ : throw new ValidationException($"The field {nameof(IpAddress)} should be a valid IP");
+ }
+
+ ///
+ /// Port of the OBS WebSocket server
+ ///
+ public int Port { get; set; } = 4444;
+
+ ///
+ /// Optional Password of the OBS WebSocket server
+ ///
+ public string Password { get; set; } = "";
+ }
+
+ ///
+ /// Connects to OBS WebSocket server
+ ///
+ public class ObsWebSocketClient : IDisposable
+ {
+ private bool disposedValue;
+ private ObsWebSocket obsWebSocket;
+
+ public bool IsConnected => obsWebSocket.IsConnected;
+
+ ///
+ /// Constructor
+ ///
+ /// Settings to connect
+ public ObsWebSocketClient()
+ {
+ this.obsWebSocket = new ObsWebSocket(); // Always not null
+ }
+
+ ///
+ /// Connects to the OBS WebSocket server
+ ///
+ ///
+ public void Connect(ObsWebSocketClientSettings settings)
+ {
+ if (obsWebSocket.IsConnected)
+ obsWebSocket.Disconnect();
+
+ obsWebSocket.Connect($"ws://{settings.IpAddress}:{settings.Port}", settings.Password ?? "");
+ }
+
+ ///
+ /// Connects to the OBS WebSocket server
+ ///
+ ///
+ public async Task ConnectAsync(ObsWebSocketClientSettings settings)
+ {
+ // At least this won't block the main thread if using from GUI
+ await Task.WhenAny(Task.Run(() => obsWebSocket.Connect($"ws://{settings.IpAddress}:{settings.Port}", "")), Task.Delay(3000));
+ }
+
+ ///
+ /// Changes OBS current scene
+ ///
+ /// The Scene name in OBS
+ /// Always true
+ public bool ChangeScene(string scene)
+ {
+ obsWebSocket.Api.SetCurrentScene(scene);
+ return true;
+ }
+
+ ///
+ /// Changes OBS current scene
+ ///
+ /// The Scene name in OBS
+ /// Always true
+ public async Task ChangeSceneAsync(string scene)
+ {
+ await Task.Run(() => obsWebSocket.Api.SetCurrentScene(scene));
+ return true;
+ }
+
+ ///
+ /// Starts recording OBS
+ ///
+ /// Always true
+ public bool StartRecording()
+ {
+ obsWebSocket.Api.StartRecording();
+ return true;
+ }
+
+ ///
+ /// Starts recording OBS
+ ///
+ /// Always true
+ public async Task StartRecordingAsync()
+ {
+ await Task.Run(() => obsWebSocket.Api.StartRecording());
+ return true;
+ }
+
+ ///
+ /// Starts recording OBS
+ ///
+ /// Always true
+ public bool StopRecording()
+ {
+ obsWebSocket.Api.StopRecording();
+ return true;
+ }
+
+ ///
+ /// Starts recording OBS
+ ///
+ /// Always true
+ public async Task StopRecordingAsync()
+ {
+ await Task.Run(() => obsWebSocket.Api.StopRecording());
+ return true;
+ }
+
+ #region Dispose
+
+ ~ObsWebSocketClient() => Dispose(disposing: false);
+
+ public void Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // TODO: dispose managed state (managed objects)
+ }
+
+ obsWebSocket.Disconnect();
+ obsWebSocket = null;
+ disposedValue = true;
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/PresentationObsSceneSwitcher/PowerPoint/PowerPointPresentationSuscriber.cs b/PresentationObsSceneSwitcher/PowerPoint/PowerPointPresentationSuscriber.cs
new file mode 100644
index 0000000..f819ba6
--- /dev/null
+++ b/PresentationObsSceneSwitcher/PowerPoint/PowerPointPresentationSuscriber.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace PresentationObsSceneSwitcher.PowerPoint
+{
+ ///
+ /// Subscribes to a PowerPoint presentation.
+ ///
+ public class PowerPointPresentationSubscriber : IPresentationSubscriber
+ {
+ ///
+ /// \( --> Literal
+ /// ((?[^\)]+)\) --> Avoid backtracking searching until a ) is found. No wildcard in regex please.
+ /// \) --> Literal
+ /// : --> Literal
+ /// \[
+ /// (?[^\]]+) --> Avoid backtracking searching until a ] is found. No wildcard in regex please.
+ /// \]
+ ///
+ /// Making it static and RegexOptions.Compiled is the best for Regex performance.
+ ///
+ private static readonly Regex extractInfoFromNotesRegex = new Regex(@"\((?[^\)]+)\):\[(?[^\]]+)\]", RegexOptions.Compiled | RegexOptions.CultureInvariant);
+
+ //private static Application powerPoint = new Application();
+
+ private readonly Dictionary suscriptions = new Dictionary();
+
+ ///
+ /// Constructor
+ ///
+ public PowerPointPresentationSubscriber()
+ {
+ PowerPointInterop.PowerPoint.SubscribeSlideShowNextSlide(async (string note) =>
+ {
+ foreach (Match match in extractInfoFromNotesRegex.Matches(note))
+ {
+ string appName = match.Groups["AppName"].Value;
+ string info = match.Groups["Info"].Value;
+
+ if (suscriptions.TryGetValue(appName, out PresentationSuscription suscription))
+ {
+ await suscription(info).ConfigureAwait(false);
+ }
+ }
+ });
+ }
+
+ ///
+ /// Subscribes an app to powerpoint slide changes
+ ///
+ /// The app subscribing
+ /// The handler of the slide change
+ ///
+ public bool Subscribe(string appName, PresentationSuscription suscription) => suscriptions.TryAdd(appName, suscription);
+ }
+}
diff --git a/PresentationObsSceneSwitcher/PresentationObsSceneSwitcher.csproj b/PresentationObsSceneSwitcher/PresentationObsSceneSwitcher.csproj
new file mode 100644
index 0000000..f61c57e
--- /dev/null
+++ b/PresentationObsSceneSwitcher/PresentationObsSceneSwitcher.csproj
@@ -0,0 +1,34 @@
+
+
+
+ Library
+ netcoreapp3.1
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .\lib\Debug\PowerPointInterop.dll
+
+
+
+
+
+
+ .\lib\Release\PowerPointInterop.dll
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PresentationObsSceneSwitcher/lib/Debug/PowerPointInterop.dll b/PresentationObsSceneSwitcher/lib/Debug/PowerPointInterop.dll
new file mode 100644
index 0000000..e52e660
Binary files /dev/null and b/PresentationObsSceneSwitcher/lib/Debug/PowerPointInterop.dll differ
diff --git a/PresentationObsSceneSwitcher/lib/Debug/PowerPointInterop.pdb b/PresentationObsSceneSwitcher/lib/Debug/PowerPointInterop.pdb
new file mode 100644
index 0000000..bb97872
Binary files /dev/null and b/PresentationObsSceneSwitcher/lib/Debug/PowerPointInterop.pdb differ
diff --git a/PresentationObsSceneSwitcher/lib/Release/PowerPointInterop.dll b/PresentationObsSceneSwitcher/lib/Release/PowerPointInterop.dll
new file mode 100644
index 0000000..36c7c95
Binary files /dev/null and b/PresentationObsSceneSwitcher/lib/Release/PowerPointInterop.dll differ
diff --git a/PresentationObsSceneSwitcher/lib/Release/PowerPointInterop.pdb b/PresentationObsSceneSwitcher/lib/Release/PowerPointInterop.pdb
new file mode 100644
index 0000000..f556791
Binary files /dev/null and b/PresentationObsSceneSwitcher/lib/Release/PowerPointInterop.pdb differ
diff --git a/PresentationObsSceneSwitcher/proyector.ico b/PresentationObsSceneSwitcher/proyector.ico
new file mode 100644
index 0000000..4ec97ec
Binary files /dev/null and b/PresentationObsSceneSwitcher/proyector.ico differ
diff --git a/PresentationObsSceneSwitcher/settings.json b/PresentationObsSceneSwitcher/settings.json
new file mode 100644
index 0000000..9756740
--- /dev/null
+++ b/PresentationObsSceneSwitcher/settings.json
@@ -0,0 +1 @@
+{"IpAddress":"127.0.0.1","Port":4444,"Password":""}
\ No newline at end of file
diff --git a/PresentationObsSceneSwitcherConsole/CommandLineApp.cs b/PresentationObsSceneSwitcherConsole/CommandLineApp.cs
new file mode 100644
index 0000000..a822137
--- /dev/null
+++ b/PresentationObsSceneSwitcherConsole/CommandLineApp.cs
@@ -0,0 +1,114 @@
+using McMaster.Extensions.CommandLineUtils;
+using Microsoft.Extensions.Logging;
+using PowerPointToOBSSceneSwitcher.Obs;
+using PresentationObsSceneSwitcherConsole;
+using System;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace PresentationObsSceneSwitcher
+{
+ public class CommandLineApp
+ {
+ [Option(Description = "Run as console app", ShortName = "cmd")]
+ public bool NoGui { get; } = false;
+
+ [Option(Description = "IpAddress", ShortName = "ip")]
+ public string IpAddress { get; }
+
+ [Option(Description = "Port", ShortName = "p")]
+ public int? Port { get; }
+
+ [Option(Description = "Optional Password", ShortName = "pass")]
+ public string Password { get; }
+
+ private readonly Func formFactory;
+ private readonly JsonSettingsRepository settingsRepository;
+ private readonly ObsWebSocketClient client;
+ private readonly IPresentationSubscriber subscriber;
+ private readonly ILogger logger;
+
+ public CommandLineApp(Func formFactory,
+ JsonSettingsRepository settingsRepository, ObsWebSocketClient client,
+ IPresentationSubscriber subscriber, ILogger logger)
+ {
+ this.formFactory = formFactory;
+ this.settingsRepository = settingsRepository;
+ this.client = client;
+ this.subscriber = subscriber;
+ this.logger = logger;
+ }
+
+ public async Task OnExecuteAsync()
+ {
+ ObsWebSocketClientSettings settings = await ReadSettings().ConfigureAwait(false);
+
+ logger.LogInformation("Try to connect using Address: {IpAddress}:{Port}", settings.IpAddress, settings.Port);
+
+ try
+ {
+ await client.ConnectAsync(settings).ConfigureAwait(false);
+ logger.LogInformation("Connected");
+ }
+ catch (Exception ex)
+ {
+ logger.LogError("Cannot connect: {Message}", ex.Message);
+ }
+
+ /* Suscribe the client. */
+ subscriber.Subscribe("OBS", async command =>
+ {
+ logger.LogTrace("Received command: {Command}", command);
+
+ if (command == "**START")
+ await client.StartRecordingAsync();
+ else if (command == "**STOP")
+ await client.StopRecordingAsync();
+ else if (string.IsNullOrEmpty(command))
+ await client.ChangeSceneAsync(command);
+ });
+
+
+ if (!NoGui)
+ {
+ logger.LogInformation("Runnig with GUI");
+ ConsoleWindowController.Hide();
+ RunGui(settings);
+
+ /* Save if running GUI. */
+ await settingsRepository.SaveAsync(settings);
+ }
+ else
+ {
+ logger.LogInformation("Runnig without GUI");
+ Console.ReadKey();
+ }
+ }
+
+ private async Task ReadSettings()
+ {
+ ObsWebSocketClientSettings settings = (await settingsRepository.LoadAsync().ConfigureAwait(false))
+ ?? new ObsWebSocketClientSettings();
+
+ if (!string.IsNullOrEmpty(IpAddress))
+ settings.IpAddress = IpAddress;
+
+ if (Port.HasValue)
+ settings.Port = Port.Value;
+
+ if (!string.IsNullOrEmpty(Password))
+ settings.Password = Password;
+
+ return settings;
+ }
+
+ private void RunGui(ObsWebSocketClientSettings settings)
+ {
+ Application.SetHighDpiMode(HighDpiMode.SystemAware);
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+
+ Application.Run(formFactory(settings));
+ }
+ }
+}
diff --git a/PresentationObsSceneSwitcherConsole/ConsoleWindowController.cs b/PresentationObsSceneSwitcherConsole/ConsoleWindowController.cs
new file mode 100644
index 0000000..85d761d
--- /dev/null
+++ b/PresentationObsSceneSwitcherConsole/ConsoleWindowController.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace PresentationObsSceneSwitcherConsole
+{
+ public class ConsoleWindowController
+ {
+ const int SW_HIDE = 0;
+ const int SW_SHOW = 5;
+
+ [DllImport("kernel32.dll")]
+ static extern IntPtr GetConsoleWindow();
+
+ [DllImport("user32.dll")]
+ static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
+
+ public static void Show()
+ {
+ ShowWindow(GetConsoleWindow(), SW_SHOW);
+ }
+
+ public static void Hide()
+ {
+ ShowWindow(GetConsoleWindow(), SW_HIDE);
+ }
+ }
+}
diff --git a/PresentationObsSceneSwitcherConsole/PresentationObsSceneSwitcherConsole.csproj b/PresentationObsSceneSwitcherConsole/PresentationObsSceneSwitcherConsole.csproj
new file mode 100644
index 0000000..b3ad9e1
--- /dev/null
+++ b/PresentationObsSceneSwitcherConsole/PresentationObsSceneSwitcherConsole.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ netcoreapp3.1
+ true
+ true
+ win-x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PresentationObsSceneSwitcherConsole/Program.cs b/PresentationObsSceneSwitcherConsole/Program.cs
new file mode 100644
index 0000000..d253093
--- /dev/null
+++ b/PresentationObsSceneSwitcherConsole/Program.cs
@@ -0,0 +1,30 @@
+using McMaster.Extensions.CommandLineUtils;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using PowerPointToOBSSceneSwitcher.Obs;
+using PresentationObsSceneSwitcher;
+using PresentationObsSceneSwitcher.PowerPoint;
+using System;
+using System.Threading.Tasks;
+
+namespace PresentationObsSceneSwitcherConsole
+{
+ internal static class Program
+ {
+ private static async Task Main(string[] args)
+ {
+ ServiceProvider services = new ServiceCollection().AddLogging(builder => builder.AddConsole().AddDebug())
+ .AddScoped()
+ .AddSingleton()
+ .AddScoped()
+ .AddScoped>(ctx =>
+ settings => new ConfigurationForm(settings, ctx.GetRequiredService()))
+ .BuildServiceProvider();
+
+ CommandLineApplication app = new CommandLineApplication();
+ app.Conventions.UseDefaultConventions().UseConstructorInjection(services);
+
+ return await app.ExecuteAsync(args);
+ }
+ }
+}
diff --git a/Program.cs b/Program.cs
index 29ef558..800a973 100644
--- a/Program.cs
+++ b/Program.cs
@@ -40,13 +40,31 @@ async static void App_SlideShowNextSlide(SlideShowWindow Wn)
{
if (line.StartsWith("OBS:")) {
line = line.Substring(4).Trim();
- Console.WriteLine($" Switching to OBS Scene named \"{line}\"");
- try { OBS.ChangeScene(line); }
- catch { Console.WriteLine($" ERROR: {ex.Message.ToString()}"); }
- break;
+ await HandleCommand(line);
}
}
}
}
+
+ static async Task HandleCommand(string command)
+ {
+ switch (command)
+ {
+ case "":
+ break;
+ case "**START":
+ OBS.StartRecording();
+ break;
+ case "**STOP":
+ OBS.StopRecording();
+ break;
+
+ default:
+ Console.WriteLine($" Switching to OBS Scene named \"{command}\"");
+ try { OBS.ChangeScene(command); }
+ catch (Exception ex) { Console.WriteLine($" ERROR: {ex.Message.ToString()}"); }
+ break;
+ }
+ }
}
}
\ No newline at end of file