diff --git a/src/matrix/calls/TODO.md b/src/matrix/calls/TODO.md index a8fbeafd..ad8fe185 100644 --- a/src/matrix/calls/TODO.md +++ b/src/matrix/calls/TODO.md @@ -96,12 +96,15 @@ party identification ## TODO Build basic version of PeerCall + - add candidates code Build basic version of GroupCall -Make it possible to olm encrypt the messages + - add state, block invalid actions +DONE: Make it possible to olm encrypt the messages Do work needed for state events - receiving (almost done?) - sending Expose call objects +expose volume events from audiotrack to group call Write view model write view diff --git a/src/matrix/calls/group/GroupCall.ts b/src/matrix/calls/group/GroupCall.ts index 7266645d..9e80b0ff 100644 --- a/src/matrix/calls/group/GroupCall.ts +++ b/src/matrix/calls/group/GroupCall.ts @@ -27,17 +27,31 @@ import type {StateEvent} from "../../storage/types"; import type {Platform} from "../../../platform/web/Platform"; import type {EncryptedMessage} from "../../e2ee/olm/Encryption"; import type {ILogItem} from "../../../logging/types"; +import type {Storage} from "../../storage/idb/Storage"; + +export enum GroupCallState { + LocalCallFeedUninitialized = "local_call_feed_uninitialized", + InitializingLocalCallFeed = "initializing_local_call_feed", + LocalCallFeedInitialized = "local_call_feed_initialized", + Joining = "entering", + Joined = "entered", + Ended = "ended", +} export type Options = Omit & { emitUpdate: (call: GroupCall, params?: any) => void; encryptDeviceMessage: (roomId: string, message: SignallingMessage, log: ILogItem) => Promise, + storage: Storage, + ownDeviceId: string }; export class GroupCall { private readonly _members: ObservableMap = new ObservableMap(); private localMedia?: Promise; private _memberOptions: MemberOptions; - + private _state: GroupCallState = GroupCallState.LocalCallFeedInitialized; + + // TODO: keep connected state and deal constructor( private callEvent: StateEvent, private readonly room: Room, @@ -52,6 +66,10 @@ export class GroupCall { }, options); } + static async create(roomId: string, options: Options): Promise { + + } + get members(): BaseObservableMap { return this._members; } get id(): string { return this.callEvent.state_key; } @@ -60,12 +78,11 @@ export class GroupCall { return this.callEvent.content["m.terminated"] === true; } - async join(tracks: Promise) { - this.localMedia = tracks.then(tracks => LocalMedia.fromTracks(tracks)); + async join(localMedia: Promise) { + this.localMedia = localMedia; + const memberContent = await this._createOrUpdateOwnMemberStateContent(); // send m.call.member state event - const request = this.options.hsApi.sendState(this.room.id, "m.call.member", this.options.ownUserId, { - - }); + const request = this.options.hsApi.sendState(this.room.id, "m.call.member", this.options.ownUserId, memberContent); await request.response(); // send invite to all members that are < my userId for (const [,member] of this._members) { @@ -106,4 +123,31 @@ export class GroupCall { // we haven't received the m.call.member yet for this caller. buffer the device messages or create the member/call anyway? } } + + private async _createOrUpdateOwnMemberStateContent() { + const {storage} = this.options; + const txn = await storage.readTxn([storage.storeNames.roomState]); + const stateEvent = await txn.roomState.get(this.room.id, "m.call.member", this.options.ownUserId); + const stateContent = stateEvent?.event?.content ?? { + ["m.calls"]: [] + }; + const callsInfo = stateContent["m.calls"]; + let callInfo = callsInfo.find(c => c["m.call_id"] === this.id); + if (!callInfo) { + callInfo = { + ["m.call_id"]: this.id, + ["m.devices"]: [] + }; + callsInfo.push(callInfo); + } + const devicesInfo = callInfo["m.devices"]; + let deviceInfo = devicesInfo.find(d => d["device_id"] === this.options.ownDeviceId); + if (!deviceInfo) { + deviceInfo = { + ["device_id"]: this.options.ownDeviceId + }; + devicesInfo.push(deviceInfo); + } + return stateContent; + } } diff --git a/src/matrix/calls/group/Member.ts b/src/matrix/calls/group/Member.ts index c6791568..cf020f37 100644 --- a/src/matrix/calls/group/Member.ts +++ b/src/matrix/calls/group/Member.ts @@ -65,7 +65,7 @@ export class Member { /** @internal */ updateCallInfo(memberCallInfo) { - + // m.calls object from the m.call.member event } /** @internal */