Merge branch 'develop' of github.com:thecodingmachine/workadventure into feature/global-message

+ migrating to protobuf messages

# Conflicts:
#	back/src/App.ts
#	back/src/Controller/IoSocketController.ts
#	back/yarn.lock
#	front/src/Connection.ts
#	front/src/Phaser/Game/GameScene.ts
#	front/src/Phaser/Login/EnableCameraScene.ts
#	front/src/WebRtc/SimplePeer.ts
This commit is contained in:
David Négrier 2020-10-01 14:11:34 +02:00
commit d3fa901691
87 changed files with 7429 additions and 1891 deletions

View file

@ -343,7 +343,7 @@ export class MediaManager {
*
* @param userId
*/
addActiveVideo(userId : string, userName: string = ""){
addActiveVideo(userId: string, userName: string = ""){
this.webrtcInAudio.play();
userName = userName.toUpperCase();
@ -368,7 +368,7 @@ export class MediaManager {
*
* @param userId
*/
addScreenSharingActiveVideo(userId : string, divImportance: DivImportance = DivImportance.Important){
addScreenSharingActiveVideo(userId: string, divImportance: DivImportance = DivImportance.Important){
//this.webrtcInAudio.play();
userId = `screen-sharing-${userId}`;
@ -387,7 +387,7 @@ export class MediaManager {
*
* @param userId
*/
disabledMicrophoneByUserId(userId: string){
disabledMicrophoneByUserId(userId: number){
const element = document.getElementById(`microphone-${userId}`);
if(!element){
return;
@ -399,7 +399,7 @@ export class MediaManager {
*
* @param userId
*/
enabledMicrophoneByUserId(userId: string){
enabledMicrophoneByUserId(userId: number){
const element = document.getElementById(`microphone-${userId}`);
if(!element){
return;
@ -411,7 +411,7 @@ export class MediaManager {
*
* @param userId
*/
disabledVideoByUserId(userId: string) {
disabledVideoByUserId(userId: number) {
let element = document.getElementById(`${userId}`);
if (element) {
element.style.opacity = "0";
@ -426,7 +426,7 @@ export class MediaManager {
*
* @param userId
*/
enabledVideoByUserId(userId: string){
enabledVideoByUserId(userId: number){
let element = document.getElementById(`${userId}`);
if(element){
element.style.opacity = "1";
@ -442,7 +442,7 @@ export class MediaManager {
* @param userId
* @param stream
*/
addStreamRemoteVideo(userId : string, stream : MediaStream){
addStreamRemoteVideo(userId: string, stream : MediaStream){
const remoteVideo = this.remoteVideo.get(userId);
if (remoteVideo === undefined) {
console.error('Unable to find video for ', userId);
@ -450,7 +450,7 @@ export class MediaManager {
}
remoteVideo.srcObject = stream;
}
addStreamRemoteScreenSharing(userId : string, stream : MediaStream){
addStreamRemoteScreenSharing(userId: string, stream : MediaStream){
// In the case of screen sharing (going both ways), we may need to create the HTML element if it does not exist yet
const remoteVideo = this.remoteVideo.get(`screen-sharing-${userId}`);
if (remoteVideo === undefined) {
@ -464,15 +464,15 @@ export class MediaManager {
*
* @param userId
*/
removeActiveVideo(userId : string){
removeActiveVideo(userId: string){
layoutManager.remove(userId);
this.remoteVideo.delete(userId);
}
removeActiveScreenSharingVideo(userId : string) {
removeActiveScreenSharingVideo(userId: string) {
this.removeActiveVideo(`screen-sharing-${userId}`)
}
isConnecting(userId : string): void {
isConnecting(userId: string): void {
const connectingSpinnerDiv = this.getSpinner(userId);
if (connectingSpinnerDiv === null) {
return;
@ -480,7 +480,7 @@ export class MediaManager {
connectingSpinnerDiv.style.display = 'block';
}
isConnected(userId : string): void {
isConnected(userId: string): void {
const connectingSpinnerDiv = this.getSpinner(userId);
if (connectingSpinnerDiv === null) {
return;
@ -488,7 +488,7 @@ export class MediaManager {
connectingSpinnerDiv.style.display = 'none';
}
isError(userId : string): void {
isError(userId: string): void {
console.log("isError", `div-${userId}`);
const element = document.getElementById(`div-${userId}`);
if(!element){
@ -500,12 +500,12 @@ export class MediaManager {
}
errorDiv.style.display = 'block';
}
isErrorScreenSharing(userId : string): void {
isErrorScreenSharing(userId: string): void {
this.isError(`screen-sharing-${userId}`);
}
private getSpinner(userId : string): HTMLDivElement|null {
private getSpinner(userId: string): HTMLDivElement|null {
const element = document.getElementById(`div-${userId}`);
if(!element){
return null;

View file

@ -1,7 +1,7 @@
import * as SimplePeerNamespace from "simple-peer";
import {mediaManager} from "./MediaManager";
import {Connection} from "../Connection";
import {TURN_SERVER, TURN_USER, TURN_PASSWORD} from "../Enum/EnvironmentVariable";
import {RoomConnection} from "../Connexion/RoomConnection";
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
@ -14,7 +14,7 @@ export class ScreenSharingPeer extends Peer {
*/
private isReceivingStream:boolean = false;
constructor(private userId: string, initiator: boolean, private connection: Connection) {
constructor(private userId: number, initiator: boolean, private connection: RoomConnection) {
super({
initiator: initiator ? initiator : false,
reconnectTimer: 10000,
@ -52,7 +52,7 @@ export class ScreenSharingPeer extends Peer {
if (message.streamEnded !== true) {
console.error('Unexpected message on screen sharing peer connection');
}
mediaManager.removeActiveScreenSharingVideo(this.userId);
mediaManager.removeActiveScreenSharingVideo("" + this.userId);
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -63,7 +63,7 @@ export class ScreenSharingPeer extends Peer {
this.on('connect', () => {
// FIXME: we need to put the loader on the screen sharing connection
mediaManager.isConnected(this.userId);
mediaManager.isConnected("" + this.userId);
console.info(`connect => ${this.userId}`);
});
@ -86,10 +86,10 @@ export class ScreenSharingPeer extends Peer {
//console.log(`ScreenSharingPeer::stream => ${this.userId}`, stream);
//console.log(`stream => ${this.userId} => `, stream);
if(!stream){
mediaManager.removeActiveScreenSharingVideo(this.userId);
mediaManager.removeActiveScreenSharingVideo("" + this.userId);
this.isReceivingStream = false;
} else {
mediaManager.addStreamRemoteScreenSharing(this.userId, stream);
mediaManager.addStreamRemoteScreenSharing("" + this.userId, stream);
this.isReceivingStream = true;
}
}
@ -100,7 +100,7 @@ export class ScreenSharingPeer extends Peer {
public destroy(error?: Error): void {
try {
mediaManager.removeActiveScreenSharingVideo(this.userId);
mediaManager.removeActiveScreenSharingVideo("" + this.userId);
// FIXME: I don't understand why "Closing connection with" message is displayed TWICE before "Nb users in peerConnectionArray"
// I do understand the method closeConnection is called twice, but I don't understand how they manage to run in parallel.
//console.log('Closing connection with '+userId);

View file

@ -1,9 +1,8 @@
import {
Connection,
WebRtcDisconnectMessageInterface,
WebRtcSignalReceivedMessageInterface,
WebRtcStartMessageInterface
} from "../Connection";
} from "../Connexion/ConnexionModels";
import {
mediaManager,
StartScreenSharingCallback,
@ -12,9 +11,10 @@ import {
} from "./MediaManager";
import {ScreenSharingPeer} from "./ScreenSharingPeer";
import {VideoPeer} from "./VideoPeer";
import {RoomConnection} from "../Connexion/RoomConnection";
export interface UserSimplePeerInterface{
userId: string;
userId: number;
name?: string;
initiator?: boolean;
}
@ -22,25 +22,25 @@ export interface UserSimplePeerInterface{
export interface PeerConnectionListener {
onConnect(user: UserSimplePeerInterface): void;
onDisconnect(userId: string): void;
onDisconnect(userId: number): void;
}
/**
* This class manages connections to all the peers in the same group as me.
*/
export class SimplePeer {
private Connection: Connection;
private Connection: RoomConnection;
private WebRtcRoomId: string;
private Users: Array<UserSimplePeerInterface> = new Array<UserSimplePeerInterface>();
private PeerScreenSharingConnectionArray: Map<string, ScreenSharingPeer> = new Map<string, ScreenSharingPeer>();
private PeerConnectionArray: Map<string, VideoPeer> = new Map<string, VideoPeer>();
private PeerScreenSharingConnectionArray: Map<number, ScreenSharingPeer> = new Map<number, ScreenSharingPeer>();
private PeerConnectionArray: Map<number, VideoPeer> = new Map<number, VideoPeer>();
private readonly sendLocalVideoStreamCallback: UpdatedLocalStreamCallback;
private readonly sendLocalScreenSharingStreamCallback: StartScreenSharingCallback;
private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback;
private readonly peerConnectionListeners: Array<PeerConnectionListener> = new Array<PeerConnectionListener>();
constructor(Connection: Connection, WebRtcRoomId: string = "test-webrtc") {
constructor(Connection: RoomConnection, WebRtcRoomId: string = "test-webrtc") {
this.Connection = Connection;
this.WebRtcRoomId = WebRtcRoomId;
// We need to go through this weird bound function pointer in order to be able to "free" this reference later.
@ -80,7 +80,7 @@ export class SimplePeer {
mediaManager.getCamera().then(() => {
//receive message start
this.Connection.receiveWebrtcStart((message: WebRtcStartMessageInterface) => {
this.Connection.receiveWebrtcStart((message: UserSimplePeerInterface) => {
this.receiveWebrtcStart(message);
});
@ -93,17 +93,22 @@ export class SimplePeer {
});
}
private receiveWebrtcStart(data: WebRtcStartMessageInterface) {
this.WebRtcRoomId = data.roomId;
this.Users = data.clients;
private receiveWebrtcStart(user: UserSimplePeerInterface) {
//this.WebRtcRoomId = data.roomId;
this.Users.push(user);
// Note: the clients array contain the list of all clients (even the ones we are already connected to in case a user joints a group)
// So we can receive a request we already had before. (which will abort at the first line of createPeerConnection)
// TODO: refactor this to only send a message to connect to one user (rather than several users).
// TODO: refactor this to only send a message to connect to one user (rather than several users). => DONE
// This would be symmetrical to the way we handle disconnection.
//console.log('Start message', data);
//start connection
this.startWebRtc();
//this.startWebRtc();
console.log('receiveWebrtcStart. Initiator: ', user.initiator)
if(!user.initiator){
return;
}
this.createPeerConnection(user);
}
/**
@ -127,6 +132,7 @@ export class SimplePeer {
if(
this.PeerConnectionArray.has(user.userId)
){
console.log('Peer connection already exists to user '+user.userId)
return null;
}
@ -138,8 +144,8 @@ export class SimplePeer {
}
}
mediaManager.removeActiveVideo(user.userId);
mediaManager.addActiveVideo(user.userId, name);
mediaManager.removeActiveVideo("" + user.userId);
mediaManager.addActiveVideo("" + user.userId, name);
const peer = new VideoPeer(user.userId, user.initiator ? user.initiator : false, this.Connection);
// When a connection is established to a video stream, and if a screen sharing is taking place,
@ -169,8 +175,8 @@ export class SimplePeer {
// We should display the screen sharing ONLY if we are not initiator
if (!user.initiator) {
mediaManager.removeActiveScreenSharingVideo(user.userId);
mediaManager.addScreenSharingActiveVideo(user.userId);
mediaManager.removeActiveScreenSharingVideo("" + user.userId);
mediaManager.addScreenSharingActiveVideo("" + user.userId);
}
const peer = new ScreenSharingPeer(user.userId, user.initiator ? user.initiator : false, this.Connection);
@ -187,7 +193,7 @@ export class SimplePeer {
*
* @param userId
*/
private closeConnection(userId : string) {
private closeConnection(userId : number) {
try {
//mediaManager.removeActiveVideo(userId);
const peer = this.PeerConnectionArray.get(userId);
@ -215,9 +221,9 @@ export class SimplePeer {
*
* @param userId
*/
private closeScreenSharingConnection(userId : string) {
private closeScreenSharingConnection(userId : number) {
try {
mediaManager.removeActiveScreenSharingVideo(userId);
mediaManager.removeActiveScreenSharingVideo("" + userId);
const peer = this.PeerScreenSharingConnectionArray.get(userId);
if (peer === undefined) {
console.warn("Tried to close connection for user "+userId+" but could not find user")
@ -291,7 +297,7 @@ export class SimplePeer {
*
* @param userId
*/
private pushVideoToRemoteUser(userId : string) {
private pushVideoToRemoteUser(userId : number) {
try {
const PeerConnection = this.PeerConnectionArray.get(userId);
if (!PeerConnection) {
@ -312,7 +318,7 @@ export class SimplePeer {
}
}
private pushScreenSharingToRemoteUser(userId : string) {
private pushScreenSharingToRemoteUser(userId : number) {
const PeerConnection = this.PeerScreenSharingConnectionArray.get(userId);
if (!PeerConnection) {
throw new Error('While pushing screen sharing, cannot find user with ID ' + userId);
@ -357,7 +363,7 @@ export class SimplePeer {
}
}
private sendLocalScreenSharingStreamToUser(userId: string): void {
private sendLocalScreenSharingStreamToUser(userId: number): void {
// If a connection already exists with user (because it is already sharing a screen with us... let's use this connection)
if (this.PeerScreenSharingConnectionArray.has(userId)) {
this.pushScreenSharingToRemoteUser(userId);
@ -374,7 +380,7 @@ export class SimplePeer {
}
}
private stopLocalScreenSharingStreamToUser(userId: string, stream: MediaStream): void {
private stopLocalScreenSharingStreamToUser(userId: number, stream: MediaStream): void {
const PeerConnectionScreenSharing = this.PeerScreenSharingConnectionArray.get(userId);
if (!PeerConnectionScreenSharing) {
throw new Error('Weird, screen sharing connection to user ' + userId + 'not found')

View file

@ -1,7 +1,7 @@
import * as SimplePeerNamespace from "simple-peer";
import {mediaManager} from "./MediaManager";
import {Connection} from "../Connection";
import {TURN_PASSWORD, TURN_SERVER, TURN_USER} from "../Enum/EnvironmentVariable";
import {RoomConnection} from "../Connexion/RoomConnection";
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
@ -9,7 +9,7 @@ const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
* A peer connection used to transmit video / audio signals between 2 peers.
*/
export class VideoPeer extends Peer {
constructor(private userId: string, initiator: boolean, private connection: Connection) {
constructor(private userId: number, initiator: boolean, private connection: RoomConnection) {
super({
initiator: initiator ? initiator : false,
reconnectTimer: 10000,
@ -63,11 +63,11 @@ export class VideoPeer extends Peer {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.on('error', (err: any) => {
console.error(`error => ${this.userId} => ${err.code}`, err);
mediaManager.isError(userId);
mediaManager.isError("" + userId);
});
this.on('connect', () => {
mediaManager.isConnected(this.userId);
mediaManager.isConnected("" + this.userId);
console.info(`connect => ${this.userId}`);
});
@ -108,7 +108,7 @@ export class VideoPeer extends Peer {
mediaManager.disabledVideoByUserId(this.userId);
mediaManager.disabledMicrophoneByUserId(this.userId);
} else {
mediaManager.addStreamRemoteVideo(this.userId, stream);
mediaManager.addStreamRemoteVideo("" + this.userId, stream);
}
}
@ -117,7 +117,7 @@ export class VideoPeer extends Peer {
*/
public destroy(error?: Error): void {
try {
mediaManager.removeActiveVideo(this.userId);
mediaManager.removeActiveVideo("" + this.userId);
// FIXME: I don't understand why "Closing connection with" message is displayed TWICE before "Nb users in peerConnectionArray"
// I do understand the method closeConnection is called twice, but I don't understand how they manage to run in parallel.
//console.log('Closing connection with '+userId);