Skip to content

Commit dedfcdc

Browse files
committed
Refix again :sad:
1 parent 8f11569 commit dedfcdc

5 files changed

Lines changed: 182 additions & 6 deletions

File tree

obs-websocket-dotnet/Events.cs

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
using System.Collections.Generic;
77
using System.Diagnostics;
88
using OBSWebsocketDotNet.Types.Events;
9+
using System.Data.Common;
10+
using System.Net.WebSockets;
11+
using Websocket.Client;
912

1013
namespace OBSWebsocketDotNet
1114
{
@@ -265,10 +268,31 @@ public partial class OBSWebsocket
265268
/// </summary>
266269
public event EventHandler<InputAudioMonitorTypeChangedEventArgs> InputAudioMonitorTypeChanged;
267270

271+
272+
private event EventHandler<InputVolumeMetersEventArgs> inputVolumeMeters;
268273
/// <summary>
269274
/// A high-volume event providing volume levels of all active inputs every 50 milliseconds.
270275
/// </summary>
271-
public event EventHandler<InputVolumeMetersEventArgs> InputVolumeMeters;
276+
public event EventHandler<InputVolumeMetersEventArgs> InputVolumeMeters
277+
{
278+
// This event needs special subscription, handle that here
279+
add
280+
{
281+
if (inputVolumeMeters == null || inputVolumeMeters.GetInvocationList().Length == 0)
282+
{
283+
RegisterEvent(EventSubscription.InputVolumeMeters);
284+
}
285+
inputVolumeMeters += value;
286+
}
287+
remove
288+
{
289+
inputVolumeMeters -= value;
290+
if (inputVolumeMeters == null || inputVolumeMeters.GetInvocationList().Length == 0)
291+
{
292+
UnRegisterEvent(EventSubscription.InputVolumeMeters);
293+
}
294+
}
295+
}
272296

273297
/// <summary>
274298
/// The replay buffer has been saved.
@@ -292,6 +316,57 @@ public partial class OBSWebsocket
292316

293317
#endregion
294318

319+
320+
#region EventSubscription
321+
322+
private EventSubscription registeredEvents = EventSubscription.All;
323+
324+
private void RegisterEvent(EventSubscription newSubscription)
325+
{
326+
registeredEvents |= newSubscription;
327+
SendReidentify();
328+
}
329+
330+
private void UnRegisterEvent(EventSubscription removeSubscription)
331+
{
332+
registeredEvents &= ~removeSubscription;
333+
SendReidentify();
334+
}
335+
336+
/// <summary>
337+
/// Send a Reidentify with new event subscriptions
338+
/// </summary>
339+
/// <returns>true if we sent the reidentify, false if failed</returns>
340+
protected bool SendReidentify()
341+
{
342+
if (wsConnection == null || !wsConnection.IsStarted) return false; // #TODO check if we are in Identified/Connected state, if we didn't send our Identify yet, we shouldn't send Reidentify now
343+
344+
var requestFields = new JObject
345+
{
346+
{ "eventSubscriptions", (uint)registeredEvents }
347+
};
348+
349+
try
350+
{
351+
// Throws ErrorResponseException if auth fails
352+
SendRequest(MessageTypes.ReIdentify, null, requestFields, false);
353+
}
354+
catch (ErrorResponseException ex)
355+
{
356+
Disconnected?.Invoke(this, new ObsDisconnectionInfo(
357+
ObsCloseCodes.UnknownReason,
358+
"Reidentify Failed",
359+
new DisconnectionInfo(DisconnectionType.Error, WebSocketCloseStatus.ProtocolError, "Reidentify Failed", String.Empty, new AuthFailureException())
360+
));
361+
Disconnect();
362+
return false;
363+
}
364+
365+
return true;
366+
}
367+
368+
#endregion
369+
295370
#region EventProcessing
296371

297372
/// <summary>
@@ -500,7 +575,7 @@ protected void ProcessEventType(string eventType, JObject body)
500575
break;
501576

502577
case nameof(InputVolumeMeters):
503-
InputVolumeMeters?.Invoke(this, new InputVolumeMetersEventArgs(JsonConvert.DeserializeObject<List<JObject>>((string)body["inputs"])));
578+
inputVolumeMeters?.Invoke(this, new InputVolumeMetersEventArgs(body["inputs"].ToObject<List<InputVolumeMeter>>()));
504579
break;
505580

506581
case nameof(ReplayBufferSaved):

obs-websocket-dotnet/OBSWebsocket.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,8 @@ protected void SendIdentify(string password, OBSAuthInfo authInfo = null)
287287
{
288288
var requestFields = new JObject
289289
{
290-
{ "rpcVersion", SUPPORTED_RPC_VERSION }
290+
{ "rpcVersion", SUPPORTED_RPC_VERSION },
291+
{ "eventSubscriptions", (uint)registeredEvents }
291292
};
292293

293294
if (authInfo != null)
@@ -301,7 +302,7 @@ protected void SendIdentify(string password, OBSAuthInfo authInfo = null)
301302

302303
SendRequest(MessageTypes.Identify, null, requestFields, false);
303304
}
304-
305+
305306
/// <summary>
306307
/// Encode a Base64-encoded SHA-256 hash
307308
/// </summary>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace OBSWebsocketDotNet.Types
6+
{
7+
[Flags]
8+
internal enum EventSubscription
9+
{
10+
None = 0,
11+
General = (1 << 0),
12+
Config = (1 << 1),
13+
Scenes = (1 << 2),
14+
Inputs = (1 << 3),
15+
Transitions = (1 << 4),
16+
Filters = (1 << 5),
17+
Outputs = (1 << 6),
18+
SceneItems = (1 << 7),
19+
MediaInputs = (1 << 8),
20+
Vendors = (1 << 9),
21+
Ui = (1 << 10),
22+
All = (General | Config | Scenes | Inputs | Transitions | Filters | Outputs | SceneItems | MediaInputs | Vendors | Ui),
23+
24+
// High volume event need separate subscription
25+
26+
InputVolumeMeters = (1 << 16),
27+
InputActiveStateChanged = (1 << 17),
28+
InputShowStateChanged = (1 << 18),
29+
SceneItemTransformChanged = (1 << 19)
30+
}
31+
}

obs-websocket-dotnet/Types/Events/InputVolumeMetersEventArgs.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ public class InputVolumeMetersEventArgs : EventArgs
1212
/// <summary>
1313
/// Array of active inputs with their associated volume levels
1414
/// </summary>
15-
public List<JObject> inputs { get; }
15+
public List<InputVolumeMeter> inputs { get; }
1616

1717
/// <summary>
1818
/// Default Constructor
1919
/// </summary>
2020
/// <param name="inputs">Collection inputs as JObjects</param>
21-
public InputVolumeMetersEventArgs(List<JObject> inputs)
21+
public InputVolumeMetersEventArgs(List<InputVolumeMeter> inputs)
2222
{
2323
this.inputs = inputs;
2424
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using Newtonsoft.Json;
2+
using Newtonsoft.Json.Linq;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Net;
6+
using System.Text;
7+
8+
namespace OBSWebsocketDotNet.Types
9+
{
10+
public class InputVolumeMeter
11+
{
12+
/// <summary>
13+
/// Name of the input
14+
/// </summary>
15+
[JsonProperty(PropertyName = "inputName")]
16+
public string InputName { set; get; }
17+
18+
// Convert json Array of 3 scalars, into a struct
19+
private class ChannelLevelConverter : JsonConverter
20+
{
21+
public override bool CanConvert(Type objectType)
22+
{
23+
return objectType == typeof(ChannelLevel);
24+
}
25+
26+
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
27+
{
28+
if (reader.TokenType != JsonToken.StartArray)
29+
throw new ProtocolViolationException("Expected InputVolumeMeter/inputLevelsMul to be an array");
30+
31+
JToken token = JToken.Load(reader);
32+
var items = token.ToObject<float[]>();
33+
34+
if (items.Length != 3)
35+
throw new ProtocolViolationException($"Expected InputVolumeMeter/inputLevelsMul to be an 3 element array, but instead got {items.Length} element array");
36+
37+
ChannelLevel contentStruct;
38+
contentStruct.PeakRaw = items[0];
39+
contentStruct.PeakWithVolume = items[1];
40+
contentStruct.magnitudeWithVolume = items[2];
41+
return contentStruct;
42+
}
43+
44+
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
45+
{
46+
throw new NotImplementedException();
47+
}
48+
}
49+
50+
[JsonConverter(typeof(ChannelLevelConverter))]
51+
public struct ChannelLevel
52+
{
53+
// https://github.com/obsproject/obs-websocket/blob/f4b72b69ce7f9ec6a5fdb1b06971e00d2b091bec/src/utils/Obs_VolumeMeter.cpp#L87
54+
55+
56+
public float magnitudeWithVolume;
57+
public float PeakWithVolume;
58+
public float PeakRaw;
59+
}
60+
61+
/// <summary>
62+
/// Array of channels on this input
63+
/// </summary>
64+
[JsonProperty(PropertyName = "inputLevelsMul")]
65+
public List<ChannelLevel> InputLevels { set; get; }
66+
67+
68+
}
69+
}

0 commit comments

Comments
 (0)