debugging unmuting not working

This commit is contained in:
Bruno Windels 2022-06-25 05:56:43 +02:00
parent d4ee19c4e4
commit 8a90c48d1e
6 changed files with 31 additions and 15 deletions

View file

@ -109,6 +109,7 @@ export class CallViewModel extends ViewModel<Options> {
// unmute but no track? // unmute but no track?
if (muteSettings.microphone && !getStreamAudioTrack(localMedia.userMedia)) { if (muteSettings.microphone && !getStreamAudioTrack(localMedia.userMedia)) {
const stream = await this.platform.mediaDevices.getMediaTracks(true, !muteSettings.camera); const stream = await this.platform.mediaDevices.getMediaTracks(true, !muteSettings.camera);
console.log("got tracks", Array.from(stream.getTracks()).map((t: MediaStreamTrack) => { return {kind: t.kind, id: t.id};}))
await this.call.setMedia(localMedia.withUserMedia(stream)); await this.call.setMedia(localMedia.withUserMedia(stream));
} else { } else {
await this.call.setMuted(muteSettings.toggleMicrophone()); await this.call.setMuted(muteSettings.toggleMicrophone());

View file

@ -45,13 +45,19 @@ export class LocalMedia {
const cloneOrAdoptStream = (oldOriginalStream: Stream | undefined, oldCloneStream: Stream | undefined, newStream: Stream | undefined): Stream | undefined => { const cloneOrAdoptStream = (oldOriginalStream: Stream | undefined, oldCloneStream: Stream | undefined, newStream: Stream | undefined): Stream | undefined => {
let stream; let stream;
if (oldOriginalStream?.id === newStream?.id) { if (oldOriginalStream?.id === newStream?.id) {
stream = oldCloneStream; return oldCloneStream;
} else { } else {
stream = newStream?.clone(); const clonedStream = newStream?.clone();
// clonedStream.addEventListener("removetrack", evt => {
// console.log(`removing track ${evt.track.id} (${evt.track.kind}) from clonedStream ${clonedStream.id}`);
// });
// console.log("got cloned tracks", Array.from(clonedStream.getTracks()).map((t: MediaStreamTrack) => { return {kind: t.kind, id: t.id};}), "from new stream", Array.from(newStream.getTracks()).map((t: MediaStreamTrack) => { return {kind: t.kind, id: t.id};}));
// console.log("stopping old audio stream", getStreamAudioTrack(oldCloneStream)?.id);
// console.log("stopping old video stream", getStreamVideoTrack(oldCloneStream)?.id);
getStreamAudioTrack(oldCloneStream)?.stop(); getStreamAudioTrack(oldCloneStream)?.stop();
getStreamVideoTrack(oldCloneStream)?.stop(); getStreamVideoTrack(oldCloneStream)?.stop();
return clonedStream;
} }
return stream;
} }
return new LocalMedia( return new LocalMedia(
cloneOrAdoptStream(oldOriginal?.userMedia, oldClone?.userMedia, this.userMedia), cloneOrAdoptStream(oldOriginal?.userMedia, oldClone?.userMedia, this.userMedia),

View file

@ -383,8 +383,7 @@ export class PeerCall implements IDisposable {
const offer = this.peerConnection.localDescription!; const offer = this.peerConnection.localDescription!;
// Get rid of any candidates waiting to be sent: they'll be included in the local // Get rid of any candidates waiting to be sent: they'll be included in the local
// description we just got and will send in the offer. // description we just got and will send in the offer.
log.log(`Discarding ${ log.set("includedCandidates", this.candidateSendQueue.length);
this.candidateSendQueue.length} candidates that will be sent in offer`);
this.candidateSendQueue = []; this.candidateSendQueue = [];
// need to queue this // need to queue this
@ -414,16 +413,20 @@ export class PeerCall implements IDisposable {
this.sendCandidateQueue(log); this.sendCandidateQueue(log);
await log.wrap("invite timeout", async log => { if (this._state === CallState.InviteSent) {
if (this._state === CallState.InviteSent) { const timeoutLog = this.logItem.child("invite timeout");
log.refDetached(timeoutLog);
// don't await this, as it would block other negotationneeded events from being processed
// as they are processed serially
timeoutLog.run(async log => {
try { await this.delay(CALL_TIMEOUT_MS); } try { await this.delay(CALL_TIMEOUT_MS); }
catch (err) { return; } catch (err) { return; }
// @ts-ignore TS doesn't take the await above into account to know that the state could have changed in between // @ts-ignore TS doesn't take the await above into account to know that the state could have changed in between
if (this._state === CallState.InviteSent) { if (this._state === CallState.InviteSent) {
this._hangup(CallErrorCode.InviteTimeout, log); this._hangup(CallErrorCode.InviteTimeout, log);
} }
} }).catch(err => {}); // prevent error from being unhandled, it will be logged already by run above
}); }
}; };
private async handleInviteGlare(content: MCallInvite<MCallBase>, partyId: PartyId, log: ILogItem): Promise<void> { private async handleInviteGlare(content: MCallInvite<MCallBase>, partyId: PartyId, log: ILogItem): Promise<void> {

View file

@ -149,11 +149,14 @@ export class GroupCall extends EventEmitter<{change: never}> {
await joinedData.logItem.wrap("join", async log => { await joinedData.logItem.wrap("join", async log => {
this._state = GroupCallState.Joining; this._state = GroupCallState.Joining;
this.emitChange(); this.emitChange();
const memberContent = await this._createJoinPayload(); await log.wrap("update member state", async log => {
// send m.call.member state event const memberContent = await this._createJoinPayload();
const request = this.options.hsApi.sendState(this.roomId, EventType.GroupCallMember, this.options.ownUserId, memberContent, {log}); log.set("payload", memberContent);
await request.response(); // send m.call.member state event
this.emitChange(); const request = this.options.hsApi.sendState(this.roomId, EventType.GroupCallMember, this.options.ownUserId, memberContent, {log});
await request.response();
this.emitChange();
});
// send invite to all members that are < my userId // send invite to all members that are < my userId
for (const [,member] of this._members) { for (const [,member] of this._members) {
this.connectToMember(member, joinedData, log); this.connectToMember(member, joinedData, log);

View file

@ -293,7 +293,7 @@ export class Member {
async setMedia(localMedia: LocalMedia, previousMedia: LocalMedia): Promise<void> { async setMedia(localMedia: LocalMedia, previousMedia: LocalMedia): Promise<void> {
const {connection} = this; const {connection} = this;
if (connection) { if (connection) {
connection.localMedia = connection.localMedia.replaceClone(connection.localMedia, previousMedia); connection.localMedia = localMedia.replaceClone(connection.localMedia, previousMedia);
await connection.peerCall?.setMedia(connection.localMedia, connection.logItem); await connection.peerCall?.setMedia(connection.localMedia, connection.logItem);
} }
} }

View file

@ -30,6 +30,9 @@ export class MediaDevicesWrapper implements IMediaDevices {
async getMediaTracks(audio: true | MediaDeviceInfo, video: boolean | MediaDeviceInfo): Promise<Stream> { async getMediaTracks(audio: true | MediaDeviceInfo, video: boolean | MediaDeviceInfo): Promise<Stream> {
const stream = await this.mediaDevices.getUserMedia(this.getUserMediaContraints(audio, video)); const stream = await this.mediaDevices.getUserMedia(this.getUserMediaContraints(audio, video));
stream.addEventListener("removetrack", evt => {
console.log(`removing track ${evt.track.id} (${evt.track.kind}) from stream ${stream.id}`);
});
return stream as Stream; return stream as Stream;
} }