301 lines
10 KiB
JavaScript
301 lines
10 KiB
JavaScript
import { AzureCommunicationTokenCredential, createIdentifierFromRawId } from '@azure/communication-common';
|
|
import { CallClient, LocalVideoStream, VideoStreamRenderer } from '@azure/communication-calling';
|
|
|
|
class VideoCall {
|
|
constructor() {
|
|
//this.isLocalVideoStartedChangedCallback = null;
|
|
//this.localVideoStreamsUpdatedCallback = null;
|
|
//this.onCreateLocalVideoStreamCallback = null;
|
|
this.onGetServerCallIDCallback = null;
|
|
//this.remoteParticipantStateChangedCallback = null;
|
|
//this.remoteParticipantsUpdatedCallback = null;
|
|
//this.remoteVideoIsAvailableChangedCallback = null;
|
|
this.stateChangedCallback = null;
|
|
this.callEndedCallback = null;
|
|
this.participantsJoinedCallback = null;
|
|
this.callsUpdatedCallback = null;
|
|
|
|
this.callAdapter = null;
|
|
this.videoContainer = null;
|
|
this.displayName = null;
|
|
this.roomID = null;
|
|
this.token = null;
|
|
this.userID = null;
|
|
|
|
this.onFetchParticipantMenuItemsCallback = null;
|
|
this.onFetchCustomButtonPropsCallbacks = [];
|
|
this.onAddParticipantCallback = null;
|
|
}
|
|
|
|
async init(options) {
|
|
let self = this;
|
|
this.stateChangedCallback = options.stateChangedCallback;
|
|
/*this.remoteParticipantsUpdatedCallback = options.remoteParticipantsUpdated;*/
|
|
/*this.isLocalVideoStartedChangedCallback = options.isLocalVideoStartedChanged;*/
|
|
/*this.localVideoStreamsUpdatedCallback = options.localVideoStreamsUpdated;*/
|
|
this.idChangedCallback = options.idChanged;
|
|
//this.onCreateLocalVideoStreamCallback = options.onCreateLocalVideoStream;
|
|
//this.remoteParticipantStateChangedCallback = options.remoteParticipantStateChanged;
|
|
//this.remoteVideoIsAvailableChangedCallback = options.remoteVideoIsAvailableChanged;
|
|
this.onGetServerCallIDCallback = options.onGetServerCallIDCallback;
|
|
this.callEndedCallback = options.callEndedCallback;
|
|
this.participantsJoinedCallback = options.participantsJoinedCallback;
|
|
this.onFetchParticipantMenuItemsCallback = options.onFetchParticipantMenuItemsCallback;
|
|
this.onFetchCustomButtonPropsCallbacks = options.onFetchCustomButtonPropsCallbacks || [];
|
|
this.onAddParticipantCallback = options.onAddParticipantCallback;
|
|
|
|
this.callAdapter = options.callAdapter;
|
|
this.videoContainer = options.videoContainer;
|
|
this.displayName = options.displayName;
|
|
this.roomID = options.roomID;
|
|
this.token = options.token;
|
|
this.userID = options.userID;
|
|
|
|
this.serverCallId;
|
|
|
|
const callControls = {
|
|
// Hide all default buttons
|
|
cameraButton: true,
|
|
endCallButton: false,
|
|
microphoneButton: false,
|
|
participantsButton: true,
|
|
screenShareButton: false,
|
|
devicesButton: false,
|
|
moreButton: false,
|
|
raiseHandButton: false,
|
|
reactionButton: false,
|
|
dtmfDialerButton: false,
|
|
holdButton: false,
|
|
peopleButton: false,
|
|
exitSpotlightButton: false,
|
|
captionsButton: false,
|
|
galleryControlsButton: false,
|
|
teamsMeetingPhoneCallButton: false,
|
|
displayType: 'compact',
|
|
|
|
// Hide the entire control bar if needed
|
|
onFetchCustomButtonProps: this.onFetchCustomButtonPropsCallbacks
|
|
};
|
|
|
|
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
|
|
const callCompositeProps = {
|
|
callControls: callControls,
|
|
formFactor: isMobile ? 'mobile' : 'desktop',
|
|
onFetchParticipantMenuItems: this.onFetchParticipantMenuItemsCallback,
|
|
options: {
|
|
callControls: callControls
|
|
}
|
|
};
|
|
|
|
const adapterArgs = {
|
|
userId: createIdentifierFromRawId(this.userID),
|
|
//credential: new AzureCommunicationTokenCredential(this.token),
|
|
token: this.token,
|
|
displayName: this.displayName,
|
|
locator: { roomId: this.roomID },
|
|
callAdapterOptions: {},
|
|
callCompositeOptions: callCompositeProps
|
|
};
|
|
|
|
this.callAdapter = await callComposite.loadCallComposite(
|
|
adapterArgs,
|
|
this.videoContainer, // container element,
|
|
callCompositeProps
|
|
);
|
|
|
|
//this.callAdapter.callAgent.on("callsUpdated", function (e) {
|
|
// e.added.forEach((addedCall) => {
|
|
// addedCall.on('stateChanged', (state) => this.stateChanged(addedCall));
|
|
// });
|
|
//});
|
|
|
|
this.callAdapter.on("callIdChanged", function (e) {
|
|
});
|
|
|
|
this.callAdapter.onStateChange(state => {
|
|
if (state.call?.info && !this.serverCallId) {
|
|
state.call.info.getServerCallId().then(result => {
|
|
this.serverCallId = result;
|
|
this.onGetServerCallIDCallback?.(result);
|
|
}).catch(err => {
|
|
console.log(err);
|
|
});
|
|
}
|
|
});
|
|
|
|
this.callAdapter.on("callEnded", function (e) {
|
|
self.callEndedCallback?.(e);
|
|
});
|
|
|
|
this.callAdapter.on("participantsJoined", function (e, f) {
|
|
self.participantsJoinedCallback?.(e, f);
|
|
});
|
|
|
|
this.callAdapter.on("onAddParticipant", function (e, f) {
|
|
self.onAddParticipantCallback?.(e, f);
|
|
});
|
|
|
|
//CallEnded
|
|
|
|
return this.callAdapter;
|
|
}
|
|
|
|
//stopLocalVideo() {
|
|
// if (this.call) {
|
|
// this.call.stopVideo(this.localVideoStream);
|
|
// }
|
|
//}
|
|
|
|
async joinRoom() {
|
|
await this.callAdapter?.joinCall({
|
|
microphoneOn: true,
|
|
cameraOn: true
|
|
});
|
|
}
|
|
|
|
async stopCall(forEveryone = false) {
|
|
await this.callAdapter?.leaveCall(forEveryone);
|
|
}
|
|
|
|
//async subscribeToCall(call) {
|
|
// try {
|
|
// call.on('idChanged', () => {
|
|
// this.idChanged?.(call.id);
|
|
// });
|
|
// call.on('stateChanged', async () => {
|
|
// this.stateChangedCallback?.(call.state);
|
|
// });
|
|
// call.on('isLocalVideoStartedChanged', () => {
|
|
// this.isLocalVideoStartedChanged?.(call.isLocalVideoStarted);
|
|
// });
|
|
// call.on('localVideoStreamsUpdated', e => {
|
|
// this.localVideoStreamsUpdated?.(e);
|
|
// });
|
|
|
|
// // Subscribe to the call's 'remoteParticipantsUpdated' event to be
|
|
// // notified when new participants are added to the call or removed from the call.
|
|
// call.on('remoteParticipantsUpdated', e => {
|
|
// this.remoteParticipantsUpdated?.(e);
|
|
|
|
// e.added.forEach(remoteParticipant => {
|
|
// this.subscribeToRemoteParticipant(remoteParticipant)
|
|
// });
|
|
// // Unsubscribe from participants that are removed from the call
|
|
// e.removed.forEach(remoteParticipant => {
|
|
// console.log('Remote participant removed from the call.');
|
|
// });
|
|
// });
|
|
|
|
// call.localVideoStreams.forEach(async (lvs) => {
|
|
// this.localVideoStream = lvs;
|
|
// await this.displayLocalVideoStream(lvs);
|
|
// });
|
|
|
|
// // Inspect the call's current remote participants and subscribe to them.
|
|
// call.remoteParticipants.forEach(remoteParticipant => {
|
|
// this.subscribeToRemoteParticipant(remoteParticipant);
|
|
// });
|
|
// } catch (error) {
|
|
// console.error(error);
|
|
// }
|
|
//}
|
|
|
|
//subscribeToRemoteParticipant(remoteParticipant) {
|
|
// try {
|
|
// // Inspect the initial remoteParticipant.state value.
|
|
// console.log(`Remote participant state: ${remoteParticipant.state}`);
|
|
// // Subscribe to remoteParticipant's 'stateChanged' event for value changes.
|
|
// remoteParticipant.on('stateChanged', () => {
|
|
// console.log(`Remote participant state changed: ${remoteParticipant.state}`, JSON.stringify(remoteParticipant));
|
|
// this.remoteParticipantStateChanged?.(remoteParticipant.state);
|
|
// });
|
|
|
|
// // Inspect the remoteParticipants's current videoStreams and subscribe to them.
|
|
// remoteParticipant.videoStreams.forEach(remoteVideoStream => {
|
|
// this.subscribeToRemoteVideoStream(remoteVideoStream);
|
|
// });
|
|
// // Subscribe to the remoteParticipant's 'videoStreamsUpdated' event to be
|
|
// // notified when the remoteParticipant adds new videoStreams and removes video streams.
|
|
// remoteParticipant.on('videoStreamsUpdated', e => {
|
|
// // Subscribe to new remote participant's video streams that were added.
|
|
// e.added.forEach(remoteVideoStream => {
|
|
// this.subscribeToRemoteVideoStream(remoteVideoStream);
|
|
// });
|
|
// // Unsubscribe from remote participant's video streams that were removed.
|
|
// e.removed.forEach(remoteVideoStream => {
|
|
// console.log('Remote participant video stream was removed.');
|
|
// })
|
|
// });
|
|
// } catch (error) {
|
|
// console.error(error);
|
|
// }
|
|
//}
|
|
|
|
//async subscribeToRemoteVideoStream(remoteVideoStream) {
|
|
// let renderer = new VideoStreamRenderer(remoteVideoStream);
|
|
// let view;
|
|
|
|
// const createView = async () => {
|
|
// // Create a renderer view for the remote video stream.
|
|
// view = await renderer.createView();
|
|
// this.remoteVideoIsAvailableChanged?.({
|
|
// isAvailable: remoteVideoStream.isAvailable,
|
|
// participantId: remoteVideoStream.tsParticipantId,
|
|
// el: view.target
|
|
// });
|
|
// }
|
|
|
|
// // Remote participant has switched video on/off
|
|
// remoteVideoStream.on('isAvailableChanged', async () => {
|
|
// try {
|
|
// if (remoteVideoStream.isAvailable) {
|
|
// await createView();
|
|
// } else {
|
|
// view?.dispose();
|
|
// }
|
|
// } catch (e) {
|
|
// console.error(e);
|
|
// }
|
|
// });
|
|
|
|
// // Remote participant has video on initially.
|
|
// if (remoteVideoStream.isAvailable) {
|
|
// try {
|
|
// await createView();
|
|
// } catch (e) {
|
|
// console.error(e);
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
//async createLocalVideoStream() {
|
|
// const camera = (await this.deviceManager.getCameras())[0];
|
|
// if (camera) {
|
|
// return new LocalVideoStream(camera);
|
|
// } else {
|
|
// console.error(`No camera device found on the system`);
|
|
// }
|
|
//}
|
|
|
|
leaveRoom() {
|
|
if (this.call) {
|
|
this.call.hangUp();
|
|
}
|
|
}
|
|
|
|
//createIdentifierFromRawId(rawId) {
|
|
// return createIdentifierFromRawId(rawId);
|
|
//}
|
|
|
|
//async displayLocalVideoStream(lvs) {
|
|
// try {
|
|
// let localVideoStreamRenderer = new VideoStreamRenderer(lvs);
|
|
// const view = await localVideoStreamRenderer.createView();
|
|
// this.onCreateLocalVideoStream?.(view.target);
|
|
// } catch (error) {
|
|
// console.error(error);
|
|
// }
|
|
//}
|
|
}
|
|
|
|
export default VideoCall; |