diff --git a/src/matrix/calls/LocalMedia.ts b/src/matrix/calls/LocalMedia.ts index 7dbc9e17..933ae89f 100644 --- a/src/matrix/calls/LocalMedia.ts +++ b/src/matrix/calls/LocalMedia.ts @@ -43,13 +43,43 @@ export class LocalMedia { return new LocalMedia(this.userMedia, this.microphoneMuted, this.cameraMuted, this.screenShare, options); } + replaceClone(oldClone: LocalMedia | undefined, oldOriginal: LocalMedia | undefined): LocalMedia { + let userMedia; + let screenShare; + const cloneOrAdoptStream = (oldOriginalStream: Stream | undefined, oldCloneStream: Stream | undefined, newStream: Stream | undefined): Stream | undefined => { + let stream; + if (oldOriginalStream?.id === newStream?.id) { + stream = oldCloneStream; + } else { + stream = newStream?.clone(); + oldCloneStream?.audioTrack?.stop(); + oldCloneStream?.videoTrack?.stop(); + } + return stream; + } + return new LocalMedia( + cloneOrAdoptStream(oldOriginal?.userMedia, oldClone?.userMedia, this.userMedia), + this.microphoneMuted, this.cameraMuted, + cloneOrAdoptStream(oldOriginal?.screenShare, oldClone?.screenShare, this.screenShare), + this.dataChannelOptions + ); + } + clone(): LocalMedia { return new LocalMedia(this.userMedia?.clone(), this.microphoneMuted, this.cameraMuted, this.screenShare?.clone(), this.dataChannelOptions); } dispose() { - this.userMedia?.audioTrack?.stop(); - this.userMedia?.videoTrack?.stop(); - this.screenShare?.videoTrack?.stop(); + this.stopExcept(undefined); + } + + stopExcept(newMedia: LocalMedia | undefined) { + if(newMedia?.userMedia?.id !== this.userMedia?.id) { + this.userMedia?.audioTrack?.stop(); + this.userMedia?.videoTrack?.stop(); + } + if(newMedia?.screenShare?.id !== this.screenShare?.id) { + this.screenShare?.videoTrack?.stop(); + } } } diff --git a/src/matrix/calls/group/GroupCall.ts b/src/matrix/calls/group/GroupCall.ts index 9fc8d1ee..cb962b86 100644 --- a/src/matrix/calls/group/GroupCall.ts +++ b/src/matrix/calls/group/GroupCall.ts @@ -124,13 +124,13 @@ export class GroupCall extends EventEmitter<{change: never}> { } async setMedia(localMedia: LocalMedia): Promise { - if (this._state === GroupCallState.Joining || this._state === GroupCallState.Joined) { - const oldMedia = this._localMedia; + if (this._state === GroupCallState.Joining || this._state === GroupCallState.Joined && this._localMedia) { + const oldMedia = this._localMedia!; this._localMedia = localMedia; await Promise.all(Array.from(this._members.values()).map(m => { - return m.setMedia(localMedia!.clone()); + return m.setMedia(localMedia, oldMedia); })); - oldMedia?.dispose(); + oldMedia?.stopExcept(localMedia); } } diff --git a/src/matrix/calls/group/Member.ts b/src/matrix/calls/group/Member.ts index 22a3d1fa..714cd821 100644 --- a/src/matrix/calls/group/Member.ts +++ b/src/matrix/calls/group/Member.ts @@ -185,11 +185,9 @@ export class Member { } /** @internal */ - async setMedia(localMedia: LocalMedia): Promise { - const oldMedia = this.localMedia; - this.localMedia = localMedia; - await this.peerCall?.setMedia(localMedia); - oldMedia?.dispose(); + async setMedia(localMedia: LocalMedia, previousMedia: LocalMedia): Promise { + this.localMedia = localMedia.replaceClone(this.localMedia, previousMedia); + await this.peerCall?.setMedia(this.localMedia); } private _createPeerCall(callId: string): PeerCall {