void GetLocalAudioVideoEvents(MessagePrefixesPair msgPfx, Queue <Event> buffer, string loggableId, ObjectTypeInfo typeInfo)
        {
            var   msg = msgPfx.Message;
            Match m;

            if ((m = localAudioVideoCtrRegex.Match(msg.Text)).Success)
            {
                buffer.Enqueue(new ObjectCreation(msg, loggableId, typeInfo));
                buffer.Enqueue(new PropertyChange(
                                   msg, loggableId, typeInfo, "device", m.Groups["device"].Value));
                if (typeInfo == localAudioObjectType || typeInfo == localVideoObjectType)
                {
                    buffer.Enqueue(new PropertyChange(msg, loggableId, typeInfo, "state", "unmuted"));
                }
            }
            else if (msg.Text == "dispose")
            {
                buffer.Enqueue(new ObjectDeletion(msg, loggableId, typeInfo));
            }
            else if ((m = localAudioVideoPropRegex.Match(msg.Text)).Success)
            {
                var value = m.Groups["value"].Value;
                buffer.Enqueue(new PropertyChange(
                                   msg, loggableId, typeInfo,
                                   m.Groups["stream"].Success ? "WebRTC stream id" :
                                   m.Groups["tracks"].Success ? "WebRTC track id" :
                                   "?", value));
                if (m.Groups["stream"].Success)
                {
                    localWebRtcStreamIdToInfo[value] = new LocalWebRTCStreamInfo()
                    {
                        symTrackId = loggableId
                    };
                }
            }
            else if (msg.Text == "mute")
            {
                buffer.Enqueue(new PropertyChange(msg, loggableId, typeInfo, "state", "muted"));
            }
            else if ((typeInfo == localAudioObjectType) && msg.Text == "unmute")
            {
                buffer.Enqueue(new PropertyChange(msg, loggableId, typeInfo, "state", "unmuted"));
            }
            else if ((typeInfo == localVideoObjectType) && msg.Text == "unmuted")
            {
                buffer.Enqueue(new PropertyChange(msg, loggableId, typeInfo, "state", "unmuted"));
            }
        }
        void GetLocalScreenEvents(MessagePrefixesPair msgPfx, Queue <Event> buffer, string loggableId)
        {
            var   msg = msgPfx.Message;
            Match m;

            if ((m = localScreenCtrRegex.Match(msg.Text)).Success)
            {
                buffer.Enqueue(new ObjectCreation(msg, loggableId, localScreenObjectType));
            }
            else if (msg.Text == "dispose")
            {
                buffer.Enqueue(new ObjectDeletion(msg, loggableId, localScreenObjectType));
            }
            else if ((m = localScreenPropRegex.Match(msg.Text)).Success)
            {
                var value = m.Groups["value"].Value;
                buffer.Enqueue(new PropertyChange(
                                   msg, loggableId, localScreenObjectType,
                                   m.Groups["streamId"].Length > 0 ? "WebRTC stream id" :
                                   m.Groups["label"].Length > 0 ? "label" :
                                   m.Groups["trackId"].Length > 0 ? "WebRTC track id" :
                                   "?",
                                   value));
                if (m.Groups["isLabel"].Length > 0 && m.Groups["prefix"].Length > 0)
                {
                    buffer.Enqueue(new PropertyChange(
                                       msg, loggableId, localScreenObjectType, "type", m.Groups["prefix"].Value));
                }
                if (m.Groups["streamId"].Length > 0)
                {
                    localWebRtcStreamIdToInfo[value] = new LocalWebRTCStreamInfo()
                    {
                        symTrackId = loggableId
                    };
                }
            }
        }