mirror of
https://github.com/vector-im/element-call.git
synced 2024-11-15 00:04:59 +08:00
Add video/mic mute
This commit is contained in:
parent
cde692f10d
commit
5851d738f8
@ -9287,7 +9287,7 @@ module.exports={
|
|||||||
"𝐴": "A",
|
"𝐴": "A",
|
||||||
"𝑨": "A",
|
"𝑨": "A",
|
||||||
"𝒜": "A",
|
"𝒜": "A",
|
||||||
"𝓐": "A",
|
"<EFBFBD><EFBFBD><EFBFBD>": "A",
|
||||||
"𝔄": "A",
|
"𝔄": "A",
|
||||||
"𝔸": "A",
|
"𝔸": "A",
|
||||||
"𝕬": "A",
|
"𝕬": "A",
|
||||||
@ -13735,7 +13735,7 @@ module.exports={
|
|||||||
"⽒": "氏",
|
"⽒": "氏",
|
||||||
"⺠": "民",
|
"⺠": "民",
|
||||||
"⽓": "气",
|
"⽓": "气",
|
||||||
"<EFBFBD><EFBFBD><EFBFBD>": "水",
|
"⽔": "水",
|
||||||
"⺡": "氵",
|
"⺡": "氵",
|
||||||
"⺢": "氺",
|
"⺢": "氺",
|
||||||
"汎": "汎",
|
"汎": "汎",
|
||||||
@ -58557,7 +58557,6 @@ class MatrixCall extends events_1.EventEmitter {
|
|||||||
}
|
}
|
||||||
this.pushLocalFeed(stream, callEventTypes_1.SDPStreamMetadataPurpose.Usermedia);
|
this.pushLocalFeed(stream, callEventTypes_1.SDPStreamMetadataPurpose.Usermedia);
|
||||||
this.setState(CallState.CreateOffer);
|
this.setState(CallState.CreateOffer);
|
||||||
logger_1.logger.info("Got local AV stream with id " + this.localUsermediaStream.id);
|
|
||||||
logger_1.logger.debug("gotUserMediaForInvite -> " + this.type);
|
logger_1.logger.debug("gotUserMediaForInvite -> " + this.type);
|
||||||
// Now we wait for the negotiationneeded event
|
// Now we wait for the negotiationneeded event
|
||||||
});
|
});
|
||||||
@ -58566,7 +58565,6 @@ class MatrixCall extends events_1.EventEmitter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.pushLocalFeed(stream, callEventTypes_1.SDPStreamMetadataPurpose.Usermedia);
|
this.pushLocalFeed(stream, callEventTypes_1.SDPStreamMetadataPurpose.Usermedia);
|
||||||
logger_1.logger.info("Got local AV stream with id " + this.localUsermediaStream.id);
|
|
||||||
this.setState(CallState.CreateAnswer);
|
this.setState(CallState.CreateAnswer);
|
||||||
let myAnswer;
|
let myAnswer;
|
||||||
try {
|
try {
|
||||||
@ -59007,6 +59005,7 @@ class MatrixCall extends events_1.EventEmitter {
|
|||||||
this.feeds.push(new callFeed_1.CallFeed(stream, userId, purpose, this.client, this.roomId, false, false));
|
this.feeds.push(new callFeed_1.CallFeed(stream, userId, purpose, this.client, this.roomId, false, false));
|
||||||
this.emit(CallEvent.FeedsChanged, this.feeds);
|
this.emit(CallEvent.FeedsChanged, this.feeds);
|
||||||
}
|
}
|
||||||
|
// TODO: Find out what is going on here
|
||||||
// why do we enable audio (and only audio) tracks here? -- matthew
|
// why do we enable audio (and only audio) tracks here? -- matthew
|
||||||
setTracksEnabled(stream.getAudioTracks(), true);
|
setTracksEnabled(stream.getAudioTracks(), true);
|
||||||
if (addToPeerConnection) {
|
if (addToPeerConnection) {
|
||||||
@ -59169,9 +59168,6 @@ class MatrixCall extends events_1.EventEmitter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (this.localUsermediaStream) {
|
|
||||||
this.gotUserMediaForAnswer(this.localUsermediaStream);
|
|
||||||
}
|
|
||||||
else if (this.waitForLocalAVStream) {
|
else if (this.waitForLocalAVStream) {
|
||||||
this.setState(CallState.WaitLocalMedia);
|
this.setState(CallState.WaitLocalMedia);
|
||||||
}
|
}
|
||||||
@ -59183,16 +59179,11 @@ class MatrixCall extends events_1.EventEmitter {
|
|||||||
* @param {MatrixCall} newCall The new call.
|
* @param {MatrixCall} newCall The new call.
|
||||||
*/
|
*/
|
||||||
replacedBy(newCall) {
|
replacedBy(newCall) {
|
||||||
logger_1.logger.debug(this.callId + " being replaced by " + newCall.callId);
|
|
||||||
if (this.state === CallState.WaitLocalMedia) {
|
if (this.state === CallState.WaitLocalMedia) {
|
||||||
logger_1.logger.debug("Telling new call to wait for local media");
|
logger_1.logger.debug("Telling new call to wait for local media");
|
||||||
newCall.waitForLocalAVStream = true;
|
newCall.waitForLocalAVStream = true;
|
||||||
}
|
}
|
||||||
else if (this.state === CallState.CreateOffer) {
|
else if ([CallState.CreateOffer, CallState.InviteSent].includes(this.state)) {
|
||||||
logger_1.logger.debug("Handing local stream to new call");
|
|
||||||
newCall.gotUserMediaForAnswer(this.localUsermediaStream);
|
|
||||||
}
|
|
||||||
else if (this.state === CallState.InviteSent) {
|
|
||||||
logger_1.logger.debug("Handing local stream to new call");
|
logger_1.logger.debug("Handing local stream to new call");
|
||||||
newCall.gotUserMediaForAnswer(this.localUsermediaStream);
|
newCall.gotUserMediaForAnswer(this.localUsermediaStream);
|
||||||
}
|
}
|
||||||
@ -59841,10 +59832,8 @@ class MatrixCall extends events_1.EventEmitter {
|
|||||||
stopAllMedia() {
|
stopAllMedia() {
|
||||||
logger_1.logger.debug(`stopAllMedia (stream=${this.localUsermediaStream})`);
|
logger_1.logger.debug(`stopAllMedia (stream=${this.localUsermediaStream})`);
|
||||||
for (const feed of this.feeds) {
|
for (const feed of this.feeds) {
|
||||||
if (!feed.isLocal()) {
|
for (const track of feed.stream.getTracks()) {
|
||||||
for (const track of feed.stream.getTracks()) {
|
track.stop();
|
||||||
track.stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60287,157 +60276,161 @@ class CallEventHandler {
|
|||||||
return type.startsWith("m.call.") || type.startsWith("org.matrix.call.");
|
return type.startsWith("m.call.") || type.startsWith("org.matrix.call.");
|
||||||
}
|
}
|
||||||
handleCallEvent(event) {
|
handleCallEvent(event) {
|
||||||
const content = event.getContent();
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const type = event.getType();
|
const content = event.getContent();
|
||||||
const weSentTheEvent = event.getSender() === this.client.credentials.userId;
|
const type = event.getType();
|
||||||
let call = content.call_id ? this.calls.get(content.call_id) : undefined;
|
const weSentTheEvent = event.getSender() === this.client.credentials.userId;
|
||||||
//console.info("RECV %s content=%s", type, JSON.stringify(content));
|
let call = content.call_id ? this.calls.get(content.call_id) : undefined;
|
||||||
if (type === event_1.EventType.CallInvite) {
|
//console.info("RECV %s content=%s", type, JSON.stringify(content));
|
||||||
// ignore invites you send
|
if (type === event_1.EventType.CallInvite) {
|
||||||
if (weSentTheEvent)
|
// ignore invites you send
|
||||||
return;
|
if (weSentTheEvent)
|
||||||
// expired call
|
return;
|
||||||
if (event.getLocalAge() > content.lifetime - RING_GRACE_PERIOD)
|
// expired call
|
||||||
return;
|
if (event.getLocalAge() > content.lifetime - RING_GRACE_PERIOD)
|
||||||
// stale/old invite event
|
return;
|
||||||
if (call && call.state === call_1.CallState.Ended)
|
// stale/old invite event
|
||||||
return;
|
if (call && call.state === call_1.CallState.Ended)
|
||||||
if (call) {
|
return;
|
||||||
logger_1.logger.log(`WARN: Already have a MatrixCall with id ${content.call_id} but got an ` +
|
|
||||||
`invite. Clobbering.`);
|
|
||||||
}
|
|
||||||
if (content.invitee && content.invitee !== this.client.getUserId()) {
|
|
||||||
return; // This invite was meant for another user in the room
|
|
||||||
}
|
|
||||||
const timeUntilTurnCresExpire = this.client.getTurnServersExpiry() - Date.now();
|
|
||||||
logger_1.logger.info("Current turn creds expire in " + timeUntilTurnCresExpire + " ms");
|
|
||||||
call = call_1.createNewMatrixCall(this.client, event.getRoomId(), { forceTURN: this.client.forceTURN });
|
|
||||||
if (!call) {
|
|
||||||
logger_1.logger.log("Incoming call ID " + content.call_id + " but this client " +
|
|
||||||
"doesn't support WebRTC");
|
|
||||||
// don't hang up the call: there could be other clients
|
|
||||||
// connected that do support WebRTC and declining the
|
|
||||||
// the call on their behalf would be really annoying.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
call.callId = content.call_id;
|
|
||||||
const invitePromise = call.initWithInvite(event);
|
|
||||||
this.calls.set(call.callId, call);
|
|
||||||
// if we stashed candidate events for that call ID, play them back now
|
|
||||||
if (this.candidateEventsByCall.get(call.callId)) {
|
|
||||||
for (const ev of this.candidateEventsByCall.get(call.callId)) {
|
|
||||||
call.onRemoteIceCandidatesReceived(ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Were we trying to call that user (room)?
|
|
||||||
let existingCall;
|
|
||||||
for (const thisCall of this.calls.values()) {
|
|
||||||
const isCalling = [call_1.CallState.WaitLocalMedia, call_1.CallState.CreateOffer, call_1.CallState.InviteSent].includes(thisCall.state);
|
|
||||||
if (call.roomId === thisCall.roomId &&
|
|
||||||
thisCall.direction === call_1.CallDirection.Outbound &&
|
|
||||||
call.invitee === thisCall.invitee &&
|
|
||||||
isCalling) {
|
|
||||||
existingCall = thisCall;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (existingCall) {
|
|
||||||
// If we've only got to wait_local_media or create_offer and
|
|
||||||
// we've got an invite, pick the incoming call because we know
|
|
||||||
// we haven't sent our invite yet otherwise, pick whichever
|
|
||||||
// call has the lowest call ID (by string comparison)
|
|
||||||
if (existingCall.state === call_1.CallState.WaitLocalMedia ||
|
|
||||||
existingCall.state === call_1.CallState.CreateOffer ||
|
|
||||||
existingCall.callId > call.callId) {
|
|
||||||
logger_1.logger.log("Glare detected: answering incoming call " + call.callId +
|
|
||||||
" and canceling outgoing call " + existingCall.callId);
|
|
||||||
existingCall.replacedBy(call);
|
|
||||||
call.answer();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logger_1.logger.log("Glare detected: rejecting incoming call " + call.callId +
|
|
||||||
" and keeping outgoing call " + existingCall.callId);
|
|
||||||
call.hangup(call_1.CallErrorCode.Replaced, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
invitePromise.then(() => {
|
|
||||||
this.client.emit("Call.incoming", call);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (type === event_1.EventType.CallCandidates) {
|
|
||||||
if (weSentTheEvent)
|
|
||||||
return;
|
|
||||||
if (!call) {
|
|
||||||
// store the candidates; we may get a call eventually.
|
|
||||||
if (!this.candidateEventsByCall.has(content.call_id)) {
|
|
||||||
this.candidateEventsByCall.set(content.call_id, []);
|
|
||||||
}
|
|
||||||
this.candidateEventsByCall.get(content.call_id).push(event);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
call.onRemoteIceCandidatesReceived(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ([event_1.EventType.CallHangup, event_1.EventType.CallReject].includes(type)) {
|
|
||||||
// Note that we also observe our own hangups here so we can see
|
|
||||||
// if we've already rejected a call that would otherwise be valid
|
|
||||||
if (!call) {
|
|
||||||
// if not live, store the fact that the call has ended because
|
|
||||||
// we're probably getting events backwards so
|
|
||||||
// the hangup will come before the invite
|
|
||||||
call = call_1.createNewMatrixCall(this.client, event.getRoomId());
|
|
||||||
if (call) {
|
if (call) {
|
||||||
call.callId = content.call_id;
|
logger_1.logger.log(`WARN: Already have a MatrixCall with id ${content.call_id} but got an ` +
|
||||||
call.initWithHangup(event);
|
`invite. Clobbering.`);
|
||||||
this.calls.set(content.call_id, call);
|
|
||||||
}
|
}
|
||||||
}
|
if (content.invitee && content.invitee !== this.client.getUserId()) {
|
||||||
else {
|
return; // This invite was meant for another user in the room
|
||||||
if (call.state !== call_1.CallState.Ended) {
|
}
|
||||||
if (type === event_1.EventType.CallHangup) {
|
const timeUntilTurnCresExpire = this.client.getTurnServersExpiry() - Date.now();
|
||||||
call.onHangupReceived(content);
|
logger_1.logger.info("Current turn creds expire in " + timeUntilTurnCresExpire + " ms");
|
||||||
|
call = call_1.createNewMatrixCall(this.client, event.getRoomId(), { forceTURN: this.client.forceTURN });
|
||||||
|
if (!call) {
|
||||||
|
logger_1.logger.log("Incoming call ID " + content.call_id + " but this client " +
|
||||||
|
"doesn't support WebRTC");
|
||||||
|
// don't hang up the call: there could be other clients
|
||||||
|
// connected that do support WebRTC and declining the
|
||||||
|
// the call on their behalf would be really annoying.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
call.callId = content.call_id;
|
||||||
|
const initWithInvitePromise = call.initWithInvite(event);
|
||||||
|
this.calls.set(call.callId, call);
|
||||||
|
// if we stashed candidate events for that call ID, play them back now
|
||||||
|
if (this.candidateEventsByCall.get(call.callId)) {
|
||||||
|
for (const ev of this.candidateEventsByCall.get(call.callId)) {
|
||||||
|
call.onRemoteIceCandidatesReceived(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Were we trying to call that user (room)?
|
||||||
|
let existingCall;
|
||||||
|
for (const thisCall of this.calls.values()) {
|
||||||
|
const isCalling = [call_1.CallState.WaitLocalMedia, call_1.CallState.CreateOffer, call_1.CallState.InviteSent].includes(thisCall.state);
|
||||||
|
if (call.roomId === thisCall.roomId &&
|
||||||
|
thisCall.direction === call_1.CallDirection.Outbound &&
|
||||||
|
call.invitee === thisCall.invitee &&
|
||||||
|
isCalling) {
|
||||||
|
existingCall = thisCall;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (existingCall) {
|
||||||
|
// If we've only got to wait_local_media or create_offer and
|
||||||
|
// we've got an invite, pick the incoming call because we know
|
||||||
|
// we haven't sent our invite yet otherwise, pick whichever
|
||||||
|
// call has the lowest call ID (by string comparison)
|
||||||
|
if (existingCall.state === call_1.CallState.WaitLocalMedia ||
|
||||||
|
existingCall.state === call_1.CallState.CreateOffer ||
|
||||||
|
existingCall.callId > call.callId) {
|
||||||
|
logger_1.logger.log("Glare detected: answering incoming call " + call.callId +
|
||||||
|
" and canceling outgoing call " + existingCall.callId);
|
||||||
|
// Await init with invite as we need a peerConn for the following methods
|
||||||
|
yield initWithInvitePromise;
|
||||||
|
existingCall.replacedBy(call);
|
||||||
|
call.answer();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
call.onRejectReceived(content);
|
logger_1.logger.log("Glare detected: rejecting incoming call " + call.callId +
|
||||||
}
|
" and keeping outgoing call " + existingCall.callId);
|
||||||
this.calls.delete(content.call_id);
|
call.hangup(call_1.CallErrorCode.Replaced, true);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// The following events need a call
|
|
||||||
if (!call)
|
|
||||||
return;
|
|
||||||
// Ignore remote echo
|
|
||||||
if (event.getContent().party_id === call.ourPartyId)
|
|
||||||
return;
|
|
||||||
switch (type) {
|
|
||||||
case event_1.EventType.CallAnswer:
|
|
||||||
if (weSentTheEvent) {
|
|
||||||
if (call.state === call_1.CallState.Ringing) {
|
|
||||||
call.onAnsweredElsewhere(content);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
call.onAnswerReceived(event);
|
initWithInvitePromise.then(() => {
|
||||||
|
this.client.emit("Call.incoming", call);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case event_1.EventType.CallSelectAnswer:
|
else if (type === event_1.EventType.CallCandidates) {
|
||||||
call.onSelectAnswerReceived(event);
|
if (weSentTheEvent)
|
||||||
break;
|
return;
|
||||||
case event_1.EventType.CallNegotiate:
|
if (!call) {
|
||||||
call.onNegotiateReceived(event);
|
// store the candidates; we may get a call eventually.
|
||||||
break;
|
if (!this.candidateEventsByCall.has(content.call_id)) {
|
||||||
case event_1.EventType.CallAssertedIdentity:
|
this.candidateEventsByCall.set(content.call_id, []);
|
||||||
case event_1.EventType.CallAssertedIdentityPrefix:
|
}
|
||||||
call.onAssertedIdentityReceived(event);
|
this.candidateEventsByCall.get(content.call_id).push(event);
|
||||||
break;
|
}
|
||||||
case event_1.EventType.CallSDPStreamMetadataChanged:
|
else {
|
||||||
case event_1.EventType.CallSDPStreamMetadataChangedPrefix:
|
call.onRemoteIceCandidatesReceived(event);
|
||||||
call.onSDPStreamMetadataChangedReceived(event);
|
}
|
||||||
break;
|
}
|
||||||
}
|
else if ([event_1.EventType.CallHangup, event_1.EventType.CallReject].includes(type)) {
|
||||||
|
// Note that we also observe our own hangups here so we can see
|
||||||
|
// if we've already rejected a call that would otherwise be valid
|
||||||
|
if (!call) {
|
||||||
|
// if not live, store the fact that the call has ended because
|
||||||
|
// we're probably getting events backwards so
|
||||||
|
// the hangup will come before the invite
|
||||||
|
call = call_1.createNewMatrixCall(this.client, event.getRoomId());
|
||||||
|
if (call) {
|
||||||
|
call.callId = content.call_id;
|
||||||
|
call.initWithHangup(event);
|
||||||
|
this.calls.set(content.call_id, call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (call.state !== call_1.CallState.Ended) {
|
||||||
|
if (type === event_1.EventType.CallHangup) {
|
||||||
|
call.onHangupReceived(content);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
call.onRejectReceived(content);
|
||||||
|
}
|
||||||
|
this.calls.delete(content.call_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The following events need a call
|
||||||
|
if (!call)
|
||||||
|
return;
|
||||||
|
// Ignore remote echo
|
||||||
|
if (event.getContent().party_id === call.ourPartyId)
|
||||||
|
return;
|
||||||
|
switch (type) {
|
||||||
|
case event_1.EventType.CallAnswer:
|
||||||
|
if (weSentTheEvent) {
|
||||||
|
if (call.state === call_1.CallState.Ringing) {
|
||||||
|
call.onAnsweredElsewhere(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
call.onAnswerReceived(event);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case event_1.EventType.CallSelectAnswer:
|
||||||
|
call.onSelectAnswerReceived(event);
|
||||||
|
break;
|
||||||
|
case event_1.EventType.CallNegotiate:
|
||||||
|
call.onNegotiateReceived(event);
|
||||||
|
break;
|
||||||
|
case event_1.EventType.CallAssertedIdentity:
|
||||||
|
case event_1.EventType.CallAssertedIdentityPrefix:
|
||||||
|
call.onAssertedIdentityReceived(event);
|
||||||
|
break;
|
||||||
|
case event_1.EventType.CallSDPStreamMetadataChanged:
|
||||||
|
case event_1.EventType.CallSDPStreamMetadataChangedPrefix:
|
||||||
|
call.onSDPStreamMetadataChangedReceived(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.CallEventHandler = CallEventHandler;
|
exports.CallEventHandler = CallEventHandler;
|
||||||
|
File diff suppressed because one or more lines are too long
@ -171,6 +171,9 @@ export class ConferenceCallManager extends EventEmitter {
|
|||||||
|
|
||||||
this.localParticipant = null;
|
this.localParticipant = null;
|
||||||
|
|
||||||
|
this.micMuted = false;
|
||||||
|
this.videoMuted = false;
|
||||||
|
|
||||||
this.client.on("RoomState.members", this._onRoomStateMembers);
|
this.client.on("RoomState.members", this._onRoomStateMembers);
|
||||||
this.client.on("Call.incoming", this._onIncomingCall);
|
this.client.on("Call.incoming", this._onIncomingCall);
|
||||||
this.callDebugger = new ConferenceCallDebugger(this);
|
this.callDebugger = new ConferenceCallDebugger(this);
|
||||||
@ -307,12 +310,66 @@ export class ConferenceCallManager extends EventEmitter {
|
|||||||
this.participants = [];
|
this.participants = [];
|
||||||
this.localParticipant.stream = null;
|
this.localParticipant.stream = null;
|
||||||
this.localParticipant.call = null;
|
this.localParticipant.call = null;
|
||||||
|
this.micMuted = false;
|
||||||
|
this.videoMuted = false;
|
||||||
clearTimeout(this._memberParticipantStateTimeout);
|
clearTimeout(this._memberParticipantStateTimeout);
|
||||||
|
|
||||||
this.emit("participants_changed");
|
this.emit("participants_changed");
|
||||||
this.emit("left");
|
this.emit("left");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setMicMuted(muted) {
|
||||||
|
this.micMuted = muted;
|
||||||
|
|
||||||
|
const localStream = this.client.localAVStream;
|
||||||
|
|
||||||
|
if (localStream) {
|
||||||
|
for (const track of localStream.getTracks()) {
|
||||||
|
if (track.kind === "audio") {
|
||||||
|
track.enabled = !this.micMuted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let participant of this.participants) {
|
||||||
|
const call = participant.call;
|
||||||
|
|
||||||
|
if (
|
||||||
|
call &&
|
||||||
|
call.localUsermediaStream &&
|
||||||
|
call.isMicrophoneMuted() !== this.micMuted
|
||||||
|
) {
|
||||||
|
call.setMicrophoneMuted(this.micMuted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setVideoMuted(muted) {
|
||||||
|
this.videoMuted = muted;
|
||||||
|
|
||||||
|
const localStream = this.client.localAVStream;
|
||||||
|
|
||||||
|
if (localStream) {
|
||||||
|
for (const track of localStream.getTracks()) {
|
||||||
|
if (track.kind === "video") {
|
||||||
|
track.enabled = !this.videoMuted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let participant of this.participants) {
|
||||||
|
const call = participant.call;
|
||||||
|
|
||||||
|
if (
|
||||||
|
call &&
|
||||||
|
call.localUsermediaStream &&
|
||||||
|
call.isLocalVideoMuted() !== this.videoMuted
|
||||||
|
) {
|
||||||
|
call.setLocalVideoMuted(this.videoMuted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
localStorage.removeItem("matrix-auth-store");
|
localStorage.removeItem("matrix-auth-store");
|
||||||
}
|
}
|
||||||
@ -557,6 +614,20 @@ export class ConferenceCallManager extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
_onCallStateChanged = (participant, call, state) => {
|
_onCallStateChanged = (participant, call, state) => {
|
||||||
|
if (
|
||||||
|
call.localUsermediaStream &&
|
||||||
|
call.isMicrophoneMuted() !== this.micMuted
|
||||||
|
) {
|
||||||
|
call.setMicrophoneMuted(this.micMuted);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
call.localUsermediaStream &&
|
||||||
|
call.isLocalVideoMuted() !== this.videoMuted
|
||||||
|
) {
|
||||||
|
call.setLocalVideoMuted(this.videoMuted);
|
||||||
|
}
|
||||||
|
|
||||||
this.emit("debugstate", participant.userId, call.callId, state);
|
this.emit("debugstate", participant.userId, call.callId, state);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,15 +139,28 @@ export function useConferenceCallManager(homeserverUrl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useVideoRoom(manager, roomId, timeout = 5000) {
|
export function useVideoRoom(manager, roomId, timeout = 5000) {
|
||||||
const [{ loading, joined, joining, room, participants, error }, setState] =
|
const [
|
||||||
useState({
|
{
|
||||||
loading: true,
|
loading,
|
||||||
joining: false,
|
joined,
|
||||||
joined: false,
|
joining,
|
||||||
room: undefined,
|
room,
|
||||||
participants: [],
|
participants,
|
||||||
error: undefined,
|
error,
|
||||||
});
|
videoMuted,
|
||||||
|
micMuted,
|
||||||
|
},
|
||||||
|
setState,
|
||||||
|
] = useState({
|
||||||
|
loading: true,
|
||||||
|
joining: false,
|
||||||
|
joined: false,
|
||||||
|
room: undefined,
|
||||||
|
participants: [],
|
||||||
|
error: undefined,
|
||||||
|
videoMuted: false,
|
||||||
|
micMuted: false,
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setState((prevState) => ({
|
setState((prevState) => ({
|
||||||
@ -305,6 +318,16 @@ export function useVideoRoom(manager, roomId, timeout = 5000) {
|
|||||||
};
|
};
|
||||||
}, [manager]);
|
}, [manager]);
|
||||||
|
|
||||||
|
const toggleMuteMic = useCallback(() => {
|
||||||
|
manager.setMicMuted(!manager.micMuted);
|
||||||
|
setState((prevState) => ({ ...prevState, micMuted: manager.micMuted }));
|
||||||
|
}, [manager]);
|
||||||
|
|
||||||
|
const toggleMuteVideo = useCallback(() => {
|
||||||
|
manager.setVideoMuted(!manager.videoMuted);
|
||||||
|
setState((prevState) => ({ ...prevState, videoMuted: manager.videoMuted }));
|
||||||
|
}, [manager]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loading,
|
loading,
|
||||||
joined,
|
joined,
|
||||||
@ -314,6 +337,10 @@ export function useVideoRoom(manager, roomId, timeout = 5000) {
|
|||||||
error,
|
error,
|
||||||
joinCall,
|
joinCall,
|
||||||
leaveCall,
|
leaveCall,
|
||||||
|
toggleMuteVideo,
|
||||||
|
toggleMuteMic,
|
||||||
|
videoMuted,
|
||||||
|
micMuted,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,10 @@ export function Room({ manager }) {
|
|||||||
error,
|
error,
|
||||||
joinCall,
|
joinCall,
|
||||||
leaveCall,
|
leaveCall,
|
||||||
|
toggleMuteVideo,
|
||||||
|
toggleMuteMic,
|
||||||
|
videoMuted,
|
||||||
|
micMuted,
|
||||||
} = useVideoRoom(manager, roomId);
|
} = useVideoRoom(manager, roomId);
|
||||||
const debugStr = query.get("debug");
|
const debugStr = query.get("debug");
|
||||||
const [debug, setDebug] = useState(debugStr === "" || debugStr === "true");
|
const [debug, setDebug] = useState(debugStr === "" || debugStr === "true");
|
||||||
@ -113,8 +117,8 @@ export function Room({ manager }) {
|
|||||||
)}
|
)}
|
||||||
{!loading && room && joined && (
|
{!loading && room && joined && (
|
||||||
<div className={styles.footer}>
|
<div className={styles.footer}>
|
||||||
<MicButton />
|
<MicButton muted={micMuted} onClick={toggleMuteMic} />
|
||||||
<VideoButton />
|
<VideoButton enabled={videoMuted} onClick={toggleMuteVideo} />
|
||||||
<HangupButton onClick={leaveCall} />
|
<HangupButton onClick={leaveCall} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
Loading…
Reference in New Issue
Block a user