diff --git a/event/content.go b/event/content.go index 29535fd4..fe58fe39 100644 --- a/event/content.go +++ b/event/content.go @@ -87,6 +87,20 @@ var TypeMap = map[Type]reflect.Type{ CallSelectAnswer: reflect.TypeOf(CallSelectAnswerEventContent{}), CallNegotiate: reflect.TypeOf(CallNegotiateEventContent{}), CallHangup: reflect.TypeOf(CallHangupEventContent{}), + + ToDeviceCallInvite: reflect.TypeOf(CallInviteEventContent{}), + ToDeviceCallCandidates: reflect.TypeOf(CallCandidatesEventContent{}), + ToDeviceCallAnswer: reflect.TypeOf(CallAnswerEventContent{}), + ToDeviceCallReject: reflect.TypeOf(CallRejectEventContent{}), + ToDeviceCallSelectAnswer: reflect.TypeOf(CallSelectAnswerEventContent{}), + ToDeviceCallNegotiate: reflect.TypeOf(CallNegotiateEventContent{}), + ToDeviceCallHangup: reflect.TypeOf(CallHangupEventContent{}), + + FocusCallTrackSubscription: reflect.TypeOf(FocusCallTrackSubscriptionEventContent{}), + FocusCallNegotiate: reflect.TypeOf(FocusCallNegotiateEventContent{}), + FocusCallSDPStreamMetadataChanged: reflect.TypeOf(FocusCallSDPStreamMetadataChangedEventContent{}), + FocusCallPing: reflect.TypeOf(FocusCallPingEventContent{}), + FocusCallPong: reflect.TypeOf(FocusCallPongEventContent{}), } // Content stores the content of a Matrix event. @@ -496,6 +510,41 @@ func (content *Content) AsCallHangup() *CallHangupEventContent { } return casted } +func (content *Content) AsFocusCallTrackSubscription() *FocusCallTrackSubscriptionEventContent { + casted, ok := content.Parsed.(*FocusCallTrackSubscriptionEventContent) + if !ok { + return &FocusCallTrackSubscriptionEventContent{} + } + return casted +} +func (content *Content) AsFocusCallNegotiate() *FocusCallNegotiateEventContent { + casted, ok := content.Parsed.(*FocusCallNegotiateEventContent) + if !ok { + return &FocusCallNegotiateEventContent{} + } + return casted +} +func (content *Content) AsFocusCallSDPStreamMetadataChanged() *FocusCallSDPStreamMetadataChangedEventContent { + casted, ok := content.Parsed.(*FocusCallSDPStreamMetadataChangedEventContent) + if !ok { + return &FocusCallSDPStreamMetadataChangedEventContent{} + } + return casted +} +func (content *Content) AsFocusCallPing() *FocusCallPingEventContent { + casted, ok := content.Parsed.(*FocusCallPingEventContent) + if !ok { + return &FocusCallPingEventContent{} + } + return casted +} +func (content *Content) AsFocusCallPong() *FocusCallPongEventContent { + casted, ok := content.Parsed.(*FocusCallPongEventContent) + if !ok { + return &FocusCallPongEventContent{} + } + return casted +} func (content *Content) AsModPolicy() *ModPolicyContent { casted, ok := content.Parsed.(*ModPolicyContent) if !ok { diff --git a/event/type.go b/event/type.go index 050b17e9..72cd1624 100644 --- a/event/type.go +++ b/event/type.go @@ -33,6 +33,8 @@ func (tc TypeClass) Name() string { return "account data" case ToDeviceEventType: return "to-device" + case FocusEventType: + return "focus" default: return "unknown" } @@ -51,6 +53,8 @@ const ( AccountDataEventType // Device-to-device events ToDeviceEventType + // Focus events + FocusEventType ) type Type struct { @@ -80,6 +84,10 @@ func (et *Type) IsToDevice() bool { return et.Class == ToDeviceEventType } +func (et *Type) IsFocus() bool { + return et.Class == FocusEventType +} + func (et *Type) IsInRoomVerification() bool { switch et.Type { case InRoomVerificationStart.Type, InRoomVerificationReady.Type, InRoomVerificationAccept.Type, @@ -124,6 +132,9 @@ func (et *Type) GuessClass() TypeClass { CallInvite.Type, CallCandidates.Type, CallAnswer.Type, CallReject.Type, CallSelectAnswer.Type, CallNegotiate.Type, CallHangup.Type, BeeperMessageStatus.Type: return MessageEventType + case FocusCallTrackSubscription.Type, FocusCallNegotiate.Type, FocusCallSDPStreamMetadataChanged.Type, FocusCallPing.Type, + FocusCallPong.Type: + return FocusEventType case ToDeviceRoomKey.Type, ToDeviceRoomKeyRequest.Type, ToDeviceForwardedRoomKey.Type, ToDeviceRoomKeyWithheld.Type: return ToDeviceEventType default: @@ -253,4 +264,21 @@ var ( ToDeviceVerificationCancel = Type{"m.key.verification.cancel", ToDeviceEventType} ToDeviceOrgMatrixRoomKeyWithheld = Type{"org.matrix.room_key.withheld", ToDeviceEventType} + + ToDeviceCallInvite = Type{"m.call.invite", ToDeviceEventType} + ToDeviceCallCandidates = Type{"m.call.candidates", ToDeviceEventType} + ToDeviceCallAnswer = Type{"m.call.answer", ToDeviceEventType} + ToDeviceCallReject = Type{"m.call.reject", ToDeviceEventType} + ToDeviceCallSelectAnswer = Type{"m.call.select_answer", ToDeviceEventType} + ToDeviceCallNegotiate = Type{"m.call.negotiate", ToDeviceEventType} + ToDeviceCallHangup = Type{"m.call.hangup", ToDeviceEventType} +) + +// Focus events +var ( + FocusCallTrackSubscription = Type{"m.call.track_subscription", FocusEventType} + FocusCallNegotiate = Type{"m.call.negotiate", FocusEventType} + FocusCallSDPStreamMetadataChanged = Type{"m.call.sdp_stream_metadata_changed", FocusEventType} + FocusCallPing = Type{"m.call.ping", FocusEventType} + FocusCallPong = Type{"m.call.pong", FocusEventType} ) diff --git a/event/voip.go b/event/voip.go index 28f56c95..5ea4529b 100644 --- a/event/voip.go +++ b/event/voip.go @@ -10,16 +10,19 @@ import ( "encoding/json" "fmt" "strconv" + + "maunium.net/go/mautrix/id" ) type CallHangupReason string const ( - CallHangupICEFailed CallHangupReason = "ice_failed" - CallHangupInviteTimeout CallHangupReason = "invite_timeout" - CallHangupUserHangup CallHangupReason = "user_hangup" - CallHangupUserMediaFailed CallHangupReason = "user_media_failed" - CallHangupUnknownError CallHangupReason = "unknown_error" + CallHangupICEFailed CallHangupReason = "ice_failed" + CallHangupInviteTimeout CallHangupReason = "invite_timeout" + CallHangupUserHangup CallHangupReason = "user_hangup" + CallHangupUserMediaFailed CallHangupReason = "user_media_failed" + CallHangupKeepAliveTimeout CallHangupReason = "keep_alive_timeout" + CallHangupUnknownError CallHangupReason = "unknown_error" ) type CallDataType string @@ -74,15 +77,46 @@ func (cv *CallVersion) Int() (int, error) { } type BaseCallEventContent struct { - CallID string `json:"call_id"` - PartyID string `json:"party_id"` - Version CallVersion `json:"version"` + CallID string `json:"call_id"` + ConfID string `json:"conf_id"` + PartyID string `json:"party_id"` + Version CallVersion `json:"version"` + DeviceID id.DeviceID `json:"device_id"` + DestSessionID id.SessionID `json:"dest_session_id"` + SenderSessionID id.SessionID `json:"sender_session_id"` } +type CallSDPStreamMetadataPurpose string + +const ( + Usermedia CallSDPStreamMetadataPurpose = "m.usermedia" + Screenshare CallSDPStreamMetadataPurpose = "m.screenshare" +) + +type CallSDPStreamMetadataTrack struct { + Kind string `json:"kind,omitempty"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` +} + +type CallSDPStreamMetadataTracks map[string]CallSDPStreamMetadataTrack + +type CallSDPStreamMetadataObject struct { + UserID id.UserID `json:"user_id"` + DeviceID id.DeviceID `json:"device_id"` + Purpose CallSDPStreamMetadataPurpose `json:"purpose"` + AudioMuted bool `json:"audio_muted"` + VideoMuted bool `json:"video_muted"` + Tracks CallSDPStreamMetadataTracks `json:"tracks"` +} + +type CallSDPStreamMetadata map[string]CallSDPStreamMetadataObject + type CallInviteEventContent struct { BaseCallEventContent - Lifetime int `json:"lifetime"` - Offer CallData `json:"offer"` + Lifetime int `json:"lifetime"` + Offer CallData `json:"offer"` + SDPStreamMetadata CallSDPStreamMetadata `json:"org.matrix.msc3077.sdp_stream_metadata"` } type CallCandidatesEventContent struct { @@ -96,7 +130,8 @@ type CallRejectEventContent struct { type CallAnswerEventContent struct { BaseCallEventContent - Answer CallData `json:"answer"` + Answer CallData `json:"answer"` + SDPStreamMetadata CallSDPStreamMetadata `json:"org.matrix.msc3077.sdp_stream_metadata"` } type CallSelectAnswerEventContent struct { @@ -106,11 +141,37 @@ type CallSelectAnswerEventContent struct { type CallNegotiateEventContent struct { BaseCallEventContent - Lifetime int `json:"lifetime"` - Description CallData `json:"description"` + Lifetime int `json:"lifetime"` + Description CallData `json:"description"` + SDPStreamMetadata CallSDPStreamMetadata `json:"org.matrix.msc3077.sdp_stream_metadata"` } type CallHangupEventContent struct { BaseCallEventContent Reason CallHangupReason `json:"reason"` } + +type FocusTrackDescription struct { + StreamID string `json:"stream_id"` + TrackID string `json:"track_id"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` +} + +type FocusCallTrackSubscriptionEventContent struct { + Subscribe []FocusTrackDescription `json:"subscribe"` + Unsubscribe []FocusTrackDescription `json:"unsubscribe"` +} + +type FocusCallNegotiateEventContent struct { + Description CallData `json:"description"` + SDPStreamMetadata CallSDPStreamMetadata `json:"sdp_stream_metadata"` +} + +type FocusCallSDPStreamMetadataChangedEventContent struct { + SDPStreamMetadata CallSDPStreamMetadata `json:"sdp_stream_metadata"` +} + +type FocusCallPingEventContent struct{} + +type FocusCallPongEventContent struct{}