From 0fc5f6e874eb4cf82635e1845dd03982c433bd1c Mon Sep 17 00:00:00 2001 From: Tino Donderwinkel Date: Mon, 23 Oct 2023 18:05:44 +0200 Subject: [PATCH] Fixed issues with ToggleRecord and ToggleRecordPause #4 --- .../MessageClasses/RequestResponseMessage.cs | 4 +- OBSClient/Messages/OutputActiveResponse.cs | 2 +- OBSClient/Messages/OutputPausedResponse.cs | 27 ++++ OBSClient/OBSClient.csproj | 2 +- OBSClient/ObsClient_RecordRequests.cs | 8 +- README.md | 6 +- SampleWindowsAppliation/Form1.Designer.cs | 135 ++++++++++++++++-- SampleWindowsAppliation/Form1.cs | 63 +++++++- 8 files changed, 226 insertions(+), 21 deletions(-) create mode 100644 OBSClient/Messages/OutputPausedResponse.cs diff --git a/OBSClient/MessageClasses/RequestResponseMessage.cs b/OBSClient/MessageClasses/RequestResponseMessage.cs index 1e6b417..d61ba2d 100644 --- a/OBSClient/MessageClasses/RequestResponseMessage.cs +++ b/OBSClient/MessageClasses/RequestResponseMessage.cs @@ -212,10 +212,10 @@ public void OnDeserialized() // Record Requests RequestType.GetRecordStatus => this.RawResponseData.Value.Deserialize(), - RequestType.ToggleRecord => null, + RequestType.ToggleRecord => this.RawResponseData.Value.Deserialize(), RequestType.StartRecord => null, RequestType.StopRecord => this.RawResponseData.Value.Deserialize(), - RequestType.ToggleRecordPause => null, + RequestType.ToggleRecordPause => this.RawResponseData.Value.Deserialize(), RequestType.PauseRecord => null, RequestType.ResumeRecord => null, diff --git a/OBSClient/Messages/OutputActiveResponse.cs b/OBSClient/Messages/OutputActiveResponse.cs index 3c57ec2..f6dd8cc 100644 --- a/OBSClient/Messages/OutputActiveResponse.cs +++ b/OBSClient/Messages/OutputActiveResponse.cs @@ -5,7 +5,7 @@ /// /// Provides the Response Data () in the Response Message () returned by OBS Studio after sending a successful request of any of these types: - /// GetVirtualCamStatus, ToggleVirtualCam, GetReplayBufferStatus, ToggleReplayBuffer, ToggleOutput and ToggleStream. + /// GetVirtualCamStatus, ToggleVirtualCam, ToggleRecord, GetReplayBufferStatus, ToggleReplayBuffer, ToggleOutput and ToggleStream. /// public class OutputActiveResponse : IResponse { diff --git a/OBSClient/Messages/OutputPausedResponse.cs b/OBSClient/Messages/OutputPausedResponse.cs new file mode 100644 index 0000000..59d2509 --- /dev/null +++ b/OBSClient/Messages/OutputPausedResponse.cs @@ -0,0 +1,27 @@ +namespace OBSStudioClient.Messages +{ + using OBSStudioClient.Interfaces; + using System.Text.Json.Serialization; + + /// + /// Provides the Response Data () in the Response Message () returned by OBS Studio after sending a successful ToggleRecordPaused request. + /// + public class OutputPausedResponse : IResponse + { + /// + /// Gets a value indicating whether the output is active. + /// + [JsonPropertyName("outputPaused")] + public bool OutputPaused { get; } + + /// + /// Initializes a new instance of the class. + /// + /// a value indicating whether the output is paused. + [JsonConstructor] + public OutputPausedResponse(bool outputPaused) + { + this.OutputPaused = outputPaused; + } + } +} diff --git a/OBSClient/OBSClient.csproj b/OBSClient/OBSClient.csproj index 8c209e4..0466d3e 100644 --- a/OBSClient/OBSClient.csproj +++ b/OBSClient/OBSClient.csproj @@ -15,7 +15,7 @@ git obs LICENSE - 1.2.1 + 1.3.0 True diff --git a/OBSClient/ObsClient_RecordRequests.cs b/OBSClient/ObsClient_RecordRequests.cs index 4e2a4af..10d2f92 100644 --- a/OBSClient/ObsClient_RecordRequests.cs +++ b/OBSClient/ObsClient_RecordRequests.cs @@ -16,9 +16,9 @@ public async Task GetRecordStatus() /// /// Toggles the status of the record output. /// - public async Task ToggleRecord() + public async Task ToggleRecord() { - await this.SendRequestAsync(); + return (await this.SendRequestAsync()).OutputActive; } /// @@ -41,9 +41,9 @@ public async Task StopRecord() /// /// Toggles pause on the record output. /// - public async Task ToggleRecordPause() + public async Task ToggleRecordPause() { - await this.SendRequestAsync(); + return (await this.SendRequestAsync()).OutputPaused; } /// diff --git a/README.md b/README.md index f4d8e9f..466e11d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # ObsClient A Complete cross platform .NET WebSocket Client for OBS Studio version 28 and up. -Currently implementing: [**obs-websocket 5.1.0 Protocol**](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md) +Currently implementing: [**obs-websocket 5.3.0 Protocol**](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md) ## Installation Install from the [NuGet Gallery](https://www.nuget.org/packages/OBSClient) -Or through the NuGet CLI: `NuGet\Install-Package OBSClient -Version 1.2.1` -From the command line: `dotnet add package OBSClient --version 1.2.1` +Or through the NuGet CLI: `NuGet\Install-Package OBSClient -Version 1.3.0` +From the command line: `dotnet add package OBSClient --version 1.3.0` ## Sample usage ``` diff --git a/SampleWindowsAppliation/Form1.Designer.cs b/SampleWindowsAppliation/Form1.Designer.cs index f71bde8..fad76b4 100644 --- a/SampleWindowsAppliation/Form1.Designer.cs +++ b/SampleWindowsAppliation/Form1.Designer.cs @@ -103,7 +103,15 @@ private void InitializeComponent() tpFiltersRequests = new TabPage(); tbMediaInputsRequests = new TabPage(); tpOutputsRequests = new TabPage(); + bnGetStreamStatus = new Button(); tbRecordRequests = new TabPage(); + btnResumeRecord = new Button(); + btnPauseRecord = new Button(); + btnToggleRecordPause = new Button(); + btnStopRecord = new Button(); + btnStartRecord = new Button(); + btnToggleRecord = new Button(); + btnGetRecordStatus = new Button(); tbSceneItemsRequests = new TabPage(); tpStreamRequests = new TabPage(); tpTransitionsRequests = new TabPage(); @@ -122,7 +130,8 @@ private void InitializeComponent() lbGroups = new ListBox(); tbNameItem = new TextBox(); label6 = new Label(); - bnGetStreamStatus = new Button(); + label7 = new Label(); + lblRecordState = new Label(); ((System.ComponentModel.ISupportInitialize)nudPort).BeginInit(); tabControl1.SuspendLayout(); tpGeneralRequests.SuspendLayout(); @@ -131,6 +140,7 @@ private void InitializeComponent() tpScenesRequests.SuspendLayout(); tpInputsRequests.SuspendLayout(); tpOutputsRequests.SuspendLayout(); + tbRecordRequests.SuspendLayout(); tpUIRequests.SuspendLayout(); this.SuspendLayout(); // @@ -936,8 +946,25 @@ private void InitializeComponent() tpOutputsRequests.Text = "Outputs Requests"; tpOutputsRequests.UseVisualStyleBackColor = true; // + // bnGetStreamStatus + // + bnGetStreamStatus.Location = new Point(0, 212); + bnGetStreamStatus.Name = "bnGetStreamStatus"; + bnGetStreamStatus.Size = new Size(340, 46); + bnGetStreamStatus.TabIndex = 9; + bnGetStreamStatus.Text = "Get Stream Status"; + bnGetStreamStatus.UseVisualStyleBackColor = true; + bnGetStreamStatus.Click += this.bnGetStreamStatus_Click; + // // tbRecordRequests // + tbRecordRequests.Controls.Add(btnResumeRecord); + tbRecordRequests.Controls.Add(btnPauseRecord); + tbRecordRequests.Controls.Add(btnToggleRecordPause); + tbRecordRequests.Controls.Add(btnStopRecord); + tbRecordRequests.Controls.Add(btnStartRecord); + tbRecordRequests.Controls.Add(btnToggleRecord); + tbRecordRequests.Controls.Add(btnGetRecordStatus); tbRecordRequests.Location = new Point(8, 46); tbRecordRequests.Name = "tbRecordRequests"; tbRecordRequests.Size = new Size(1241, 450); @@ -945,6 +972,76 @@ private void InitializeComponent() tbRecordRequests.Text = "Record Requests"; tbRecordRequests.UseVisualStyleBackColor = true; // + // btnResumeRecord + // + btnResumeRecord.Location = new Point(3, 316); + btnResumeRecord.Name = "btnResumeRecord"; + btnResumeRecord.Size = new Size(340, 46); + btnResumeRecord.TabIndex = 15; + btnResumeRecord.Text = "Resume Record"; + btnResumeRecord.UseVisualStyleBackColor = true; + btnResumeRecord.Click += this.btnResumeRecord_Click; + // + // btnPauseRecord + // + btnPauseRecord.Location = new Point(3, 264); + btnPauseRecord.Name = "btnPauseRecord"; + btnPauseRecord.Size = new Size(340, 46); + btnPauseRecord.TabIndex = 14; + btnPauseRecord.Text = "Pause Record"; + btnPauseRecord.UseVisualStyleBackColor = true; + btnPauseRecord.Click += this.btnPauseRecord_Click; + // + // btnToggleRecordPause + // + btnToggleRecordPause.Location = new Point(3, 212); + btnToggleRecordPause.Name = "btnToggleRecordPause"; + btnToggleRecordPause.Size = new Size(340, 46); + btnToggleRecordPause.TabIndex = 13; + btnToggleRecordPause.Text = "Toggle Record Pause"; + btnToggleRecordPause.UseVisualStyleBackColor = true; + btnToggleRecordPause.Click += this.btnToggleRecordPause_Click; + // + // btnStopRecord + // + btnStopRecord.Location = new Point(3, 160); + btnStopRecord.Name = "btnStopRecord"; + btnStopRecord.Size = new Size(340, 46); + btnStopRecord.TabIndex = 12; + btnStopRecord.Text = "Stop Record"; + btnStopRecord.UseVisualStyleBackColor = true; + btnStopRecord.Click += this.btnStopRecord_Click; + // + // btnStartRecord + // + btnStartRecord.Location = new Point(3, 108); + btnStartRecord.Name = "btnStartRecord"; + btnStartRecord.Size = new Size(340, 46); + btnStartRecord.TabIndex = 11; + btnStartRecord.Text = "Start Record"; + btnStartRecord.UseVisualStyleBackColor = true; + btnStartRecord.Click += this.btnStartRecord_Click; + // + // btnToggleRecord + // + btnToggleRecord.Location = new Point(3, 56); + btnToggleRecord.Name = "btnToggleRecord"; + btnToggleRecord.Size = new Size(340, 46); + btnToggleRecord.TabIndex = 10; + btnToggleRecord.Text = "Toggle Record"; + btnToggleRecord.UseVisualStyleBackColor = true; + btnToggleRecord.Click += this.btnToggleRecord_Click; + // + // btnGetRecordStatus + // + btnGetRecordStatus.Location = new Point(3, 4); + btnGetRecordStatus.Name = "btnGetRecordStatus"; + btnGetRecordStatus.Size = new Size(340, 46); + btnGetRecordStatus.TabIndex = 9; + btnGetRecordStatus.Text = "Get Record Status"; + btnGetRecordStatus.UseVisualStyleBackColor = true; + btnGetRecordStatus.Click += this.btnGetRecordStatus_Click; + // // tbSceneItemsRequests // tbSceneItemsRequests.Location = new Point(8, 46); @@ -1118,21 +1215,31 @@ private void InitializeComponent() label6.TabIndex = 25; label6.Text = "Item Name:"; // - // bnGetStreamStatus + // label7 // - bnGetStreamStatus.Location = new Point(0, 212); - bnGetStreamStatus.Name = "bnGetStreamStatus"; - bnGetStreamStatus.Size = new Size(340, 46); - bnGetStreamStatus.TabIndex = 9; - bnGetStreamStatus.Text = "Get Stream Status"; - bnGetStreamStatus.UseVisualStyleBackColor = true; - bnGetStreamStatus.Click += this.bnGetStreamStatus_Click; + label7.AutoSize = true; + label7.Location = new Point(1307, 22); + label7.Name = "label7"; + label7.Size = new Size(152, 32); + label7.TabIndex = 26; + label7.Text = "Record State:"; + // + // lblRecordState + // + lblRecordState.AutoSize = true; + lblRecordState.Location = new Point(1465, 22); + lblRecordState.Name = "lblRecordState"; + lblRecordState.Size = new Size(56, 32); + lblRecordState.TabIndex = 27; + lblRecordState.Text = "N/A"; // // Form1 // this.AutoScaleDimensions = new SizeF(13F, 32F); this.AutoScaleMode = AutoScaleMode.Font; this.ClientSize = new Size(1986, 849); + this.Controls.Add(lblRecordState); + this.Controls.Add(label7); this.Controls.Add(label6); this.Controls.Add(tbNameItem); this.Controls.Add(label5); @@ -1159,6 +1266,7 @@ private void InitializeComponent() tpScenesRequests.ResumeLayout(false); tpInputsRequests.ResumeLayout(false); tpOutputsRequests.ResumeLayout(false); + tbRecordRequests.ResumeLayout(false); tpUIRequests.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -1261,5 +1369,14 @@ private void InitializeComponent() private Button btnOpenSourceProjectorOnMonitor; private Button btnOpenVideoMixProjectorWindow; private Button bnGetStreamStatus; + private Button btnResumeRecord; + private Button btnPauseRecord; + private Button btnToggleRecordPause; + private Button btnStopRecord; + private Button btnStartRecord; + private Button btnToggleRecord; + private Button btnGetRecordStatus; + private Label label7; + private Label lblRecordState; } } \ No newline at end of file diff --git a/SampleWindowsAppliation/Form1.cs b/SampleWindowsAppliation/Form1.cs index bae770d..8df33eb 100644 --- a/SampleWindowsAppliation/Form1.cs +++ b/SampleWindowsAppliation/Form1.cs @@ -15,6 +15,7 @@ public partial class Form1 : Form private delegate void SafeListboxRemove(object itemToRemove, ListBox listBox); private delegate void SafeListboxRefresh(ListBox listBox); private delegate void SafeUpdateTitle(); + private delegate void SafeUpdateRecordState(string text); private const string Title = "Obs Client"; public Form1() { @@ -245,6 +246,8 @@ private Task ReplayBufferSaved(object? sender, ReplayBufferSavedEventArgs e) private Task RecordStateChanged(object? sender, RecordStateChangedEventArgs e) { + var active = e.OutputActive ? "Active" : "Inactive"; + RefreshRecordState($"{e.OutputState} ({active})"); return Task.CompletedTask; } @@ -424,6 +427,19 @@ private void RefreshListbox(ListBox listBox) } } + private void RefreshRecordState(string text) + { + if (lblRecordState.InvokeRequired) + { + var d = new SafeUpdateRecordState(RefreshRecordState); + lblRecordState.Invoke(d, new object[] { text }); + } + else + { + lblRecordState.Text = text; + } + } + private async void button1_Click(object sender, EventArgs e) { var result = await _client.ConnectAsync(this.tbPassword.Text, this.tbHostname.Text, Convert.ToInt32(this.nudPort.Value)); @@ -689,7 +705,7 @@ private async void bnGetStreamStatus_Click(object sender, EventArgs e) var response = await _client.GetStreamStatus(); var result = string.Empty; result += $"OutputActive: {response.OutputActive}" + Environment.NewLine; - result += $"OutputActive: {response.OutputBytes}" + Environment.NewLine; + result += $"OutputBytes: {response.OutputBytes}" + Environment.NewLine; result += $"OutputCongestion: {response.OutputCongestion}" + Environment.NewLine; result += $"OutputDuration: {response.OutputDuration}" + Environment.NewLine; result += $"OutputReconnecting: {response.OutputReconnecting}" + Environment.NewLine; @@ -698,5 +714,50 @@ private async void bnGetStreamStatus_Click(object sender, EventArgs e) result += $"OutputTotalFrames: {response.OutputTotalFrames}" + Environment.NewLine; MessageBox.Show(result, "GetStreamStatus"); } + + private async void btnGetRecordStatus_Click(object sender, EventArgs e) + { + var response = await _client.GetRecordStatus(); + var result = string.Empty; + result += $"OutputActive: {response.OutputActive}" + Environment.NewLine; + result += $"OutputBytes: {response.OutputBytes}" + Environment.NewLine; + result += $"OutputDuration: {response.OutputDuration}" + Environment.NewLine; + result += $"OutputPaused: {response.OutputPaused}" + Environment.NewLine; + result += $"OutputTimecode: {response.OutputTimecode}" + Environment.NewLine; + MessageBox.Show(result, "GetRecordStatus"); + } + + private async void btnToggleRecord_Click(object sender, EventArgs e) + { + var result = await _client.ToggleRecord(); + MessageBox.Show(result.ToString(), "ToggleRecord"); + } + + private async void btnStartRecord_Click(object sender, EventArgs e) + { + await _client.StartRecord(); + } + + private async void btnStopRecord_Click(object sender, EventArgs e) + { + var result = await _client.StopRecord(); + MessageBox.Show(result, "StopRecord"); + } + + private async void btnToggleRecordPause_Click(object sender, EventArgs e) + { + var result = await _client.ToggleRecordPause(); + MessageBox.Show(result.ToString(), "ToggleRecordPause"); + } + + private async void btnPauseRecord_Click(object sender, EventArgs e) + { + await _client.PauseRecord(); + } + + private async void btnResumeRecord_Click(object sender, EventArgs e) + { + await _client.ResumeRecord(); + } } } \ No newline at end of file