public async ValueTask <Guid> ObsSend(object message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            ObsRequestMetadata metadata = new ObsRequestMetadata()
            {
                RequestGuid         = (message as RequestBase).MessageId,
                OriginalRequestType = (message as RequestBase).RequestType,
                OriginalRequestData = message
            };

            sentMessageGuids.Add(metadata.RequestGuid, metadata);
            await SendMessageAsync(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(message))).ConfigureAwait(false);

            return(metadata.RequestGuid);
        }
        private async Task OBS_ParseJson(MemoryStream message)
        {
            using JsonDocument document = GetJsonDocumentFromMemoryStream(message);
            JsonElement root = document.RootElement;

            JsonElement sourceType;

            if (root.TryGetProperty("message-id", out JsonElement messageIdJson))
            {
                bool sentMessageGuidExists         = false;
                ObsRequestMetadata requestMetadata = null;
                if (Guid.TryParse(messageIdJson.GetString(), out Guid guid))
                {
                    sentMessageGuidExists = sentMessageGuids.TryGetValue(guid, out requestMetadata);
                }
                root.TryGetProperty("status", out JsonElement statusJson);
                if (sentMessageGuidExists)
                {
                    ObsReplyObject obsReply = new ObsReplyObject()
                    {
                        MessageId = guid,
                        Status    = statusJson.GetString()
                    };
                    if (sentMessageGuidExists)
                    {
                        obsReply.RequestMetadata = requestMetadata;
                        sentMessageGuids.Remove(guid);
                    }
                    if (Enum.TryParse(requestMetadata.OriginalRequestType.ToString(), out ObsRequestType reqType))
                    {
                        obsReply.RequestType = reqType;
                    }

                    switch (obsReply.RequestType)
                    {
                    case ObsRequestType.GetSourceSettings:
                    case ObsRequestType.SetSourceSettings:
                        root.TryGetProperty("sourceType", out sourceType);
                        obsReply.SourceType = ObsTypes.ObsTypeNameDictionary[sourceType.ToString()];
                        break;

                    case ObsRequestType.GetSourceFilterInfo:
                        root.TryGetProperty("type", out sourceType);
                        obsReply.SourceType = ObsTypes.ObsTypeNameDictionary[sourceType.ToString()];
                        break;

                    default:
                        break;
                    }
                    await ParseReply(message, obsReply).ConfigureAwait(false);
                }
                else
                {
                    Trace.WriteLine($"message-id {messageIdJson} received, but no matching request found.");
                }
            }
            else if (root.TryGetProperty("update-type", out JsonElement updateTypeJson))
            {
                Trace.WriteLine($"Received a message of type {updateTypeJson}.");
                bool           isStreaming = root.TryGetProperty("stream-timecode", out JsonElement jsonStreamTimecode);
                bool           isRecording = root.TryGetProperty("rec-timecode", out JsonElement jsonRecTimecode);
                ObsEventObject obsEvent    = new ObsEventObject();
                if (Enum.TryParse(updateTypeJson.GetString(), out ObsEventType eventType))
                {
                    obsEvent.EventType = eventType;
                }
                switch (obsEvent.EventType)
                {
                case ObsEventType.SourceCreated:
                    root.TryGetProperty("sourceKind", out sourceType);
                    obsEvent.SourceType = ObsTypes.ObsTypeNameDictionary[sourceType.ToString()];
                    break;

                case ObsEventType.SourceFilterAdded:
                    root.TryGetProperty("filterType", out sourceType);
                    obsEvent.SourceType = ObsTypes.ObsTypeNameDictionary[sourceType.ToString()];
                    break;

                default:
                    break;
                }
                await ParseEvent(message, obsEvent).ConfigureAwait(false);
            }
            else
            {
                Trace.WriteLine("Unexpected JSON.");
            }
        }