2021-05-12 09:13:25 +02:00
import type {
2020-08-20 00:05:00 +02:00
WebRtcDisconnectMessageInterface ,
2020-08-20 16:56:10 +02:00
WebRtcSignalReceivedMessageInterface ,
2020-09-25 18:29:22 +02:00
} from "../Connexion/ConnexionModels" ;
2020-08-31 15:21:05 +02:00
import {
mediaManager ,
StartScreenSharingCallback ,
StopScreenSharingCallback ,
UpdatedLocalStreamCallback
} from "./MediaManager" ;
2020-08-20 16:56:10 +02:00
import { ScreenSharingPeer } from "./ScreenSharingPeer" ;
2021-02-02 18:19:51 +01:00
import { MESSAGE_TYPE_BLOCKED , MESSAGE_TYPE_CONSTRAINT , MESSAGE_TYPE_MESSAGE , VideoPeer } from "./VideoPeer" ;
2021-05-12 09:13:25 +02:00
import type { RoomConnection } from "../Connexion/RoomConnection" ;
2021-01-29 21:09:10 +01:00
import { connectionManager } from "../Connexion/ConnectionManager" ;
import { GameConnexionTypes } from "../Url/UrlManager" ;
2021-02-02 18:19:51 +01:00
import { blackListManager } from "./BlackListManager" ;
2021-05-19 11:17:43 +02:00
import { get } from "svelte/store" ;
2021-05-29 22:04:08 +02:00
import { localStreamStore , LocalStreamStoreValue , obtainedMediaConstraintStore } from "../Stores/MediaStore" ;
import { screenSharingLocalStreamStore } from "../Stores/ScreenSharingStore" ;
import { DivImportance , layoutManager } from "./LayoutManager" ;
import { HtmlUtils } from "./HtmlUtils" ;
2020-04-25 16:05:33 +02:00
2020-06-08 09:20:36 +02:00
export interface UserSimplePeerInterface {
2020-09-18 13:57:38 +02:00
userId : number ;
2020-05-14 20:39:30 +02:00
name? : string ;
initiator? : boolean ;
2021-02-16 09:58:08 +01:00
webRtcUser? : string | undefined ;
webRtcPassword? : string | undefined ;
2020-04-26 19:59:51 +02:00
}
2020-06-05 13:07:18 +02:00
2020-08-17 16:12:53 +02:00
export interface PeerConnectionListener {
2020-08-18 00:12:38 +02:00
onConnect ( user : UserSimplePeerInterface ) : void ;
2020-08-17 16:12:53 +02:00
2020-09-18 13:57:38 +02:00
onDisconnect ( userId : number ) : void ;
2020-08-17 16:12:53 +02:00
}
2020-06-05 13:07:18 +02:00
/ * *
* This class manages connections to all the peers in the same group as me .
* /
2020-06-03 22:32:43 +02:00
export class SimplePeer {
2020-11-27 14:51:50 +01:00
private Users : Array < UserSimplePeerInterface > = new Array < UserSimplePeerInterface > ( ) ; //todo: this array should be fusionned with PeerConnectionArray
2020-05-01 21:15:00 +02:00
2020-09-18 13:57:38 +02:00
private PeerScreenSharingConnectionArray : Map < number , ScreenSharingPeer > = new Map < number , ScreenSharingPeer > ( ) ;
private PeerConnectionArray : Map < number , VideoPeer > = new Map < number , VideoPeer > ( ) ;
2020-08-31 15:21:05 +02:00
private readonly sendLocalScreenSharingStreamCallback : StartScreenSharingCallback ;
private readonly stopLocalScreenSharingStreamCallback : StopScreenSharingCallback ;
2021-05-29 22:04:08 +02:00
private readonly unsubscribers : ( ( ) = > void ) [ ] = [ ] ;
2020-08-17 16:12:53 +02:00
private readonly peerConnectionListeners : Array < PeerConnectionListener > = new Array < PeerConnectionListener > ( ) ;
2021-02-02 18:19:51 +01:00
private readonly userId : number ;
2021-02-18 11:52:30 +01:00
private lastWebrtcUserName : string | undefined ;
private lastWebrtcPassword : string | undefined ;
2020-04-25 16:05:33 +02:00
2020-11-10 13:00:14 +01:00
constructor ( private Connection : RoomConnection , private enableReporting : boolean , private myName : string ) {
2020-06-23 14:56:57 +02:00
// We need to go through this weird bound function pointer in order to be able to "free" this reference later.
2020-08-20 00:05:00 +02:00
this . sendLocalScreenSharingStreamCallback = this . sendLocalScreenSharingStream . bind ( this ) ;
2020-08-21 22:53:17 +02:00
this . stopLocalScreenSharingStreamCallback = this . stopLocalScreenSharingStream . bind ( this ) ;
2020-10-13 19:56:42 +02:00
2021-05-29 22:04:08 +02:00
this . unsubscribers . push ( localStreamStore . subscribe ( ( streamResult ) = > {
this . sendLocalVideoStream ( streamResult ) ;
} ) ) ;
let localScreenCapture : MediaStream | null = null ;
this . unsubscribers . push ( screenSharingLocalStreamStore . subscribe ( ( streamResult ) = > {
if ( streamResult . type === 'error' ) {
// Let's ignore screen sharing errors, we will deal with those in a different way.
return ;
}
if ( streamResult . stream !== null ) {
localScreenCapture = streamResult . stream ;
this . sendLocalScreenSharingStream ( localScreenCapture ) ;
} else {
if ( localScreenCapture ) {
this . stopLocalScreenSharingStream ( localScreenCapture ) ;
localScreenCapture = null ;
}
}
} ) ) ;
2021-02-02 18:19:51 +01:00
this . userId = Connection . getUserId ( ) ;
2020-04-29 01:40:32 +02:00
this . initialise ( ) ;
}
2020-08-17 16:12:53 +02:00
public registerPeerConnectionListener ( peerConnectionListener : PeerConnectionListener ) {
this . peerConnectionListeners . push ( peerConnectionListener ) ;
}
public getNbConnections ( ) : number {
2021-03-19 15:03:55 +01:00
return this . Users . length ;
2020-08-17 16:12:53 +02:00
}
2020-04-29 01:40:32 +02:00
/ * *
* permit to listen when user could start visio
* /
2020-05-02 20:46:02 +02:00
private initialise() {
2020-04-25 16:05:33 +02:00
2020-05-01 21:15:00 +02:00
//receive signal by gemer
2020-08-20 16:56:10 +02:00
this . Connection . receiveWebrtcSignal ( ( message : WebRtcSignalReceivedMessageInterface ) = > {
2020-05-01 21:15:00 +02:00
this . receiveWebrtcSignal ( message ) ;
} ) ;
2020-04-25 16:05:33 +02:00
2020-06-11 23:18:06 +02:00
//receive signal by gemer
2020-08-20 16:56:10 +02:00
this . Connection . receiveWebrtcScreenSharingSignal ( ( message : WebRtcSignalReceivedMessageInterface ) = > {
2020-06-11 23:18:06 +02:00
this . receiveWebrtcScreenSharingSignal ( message ) ;
} ) ;
2020-08-20 00:05:00 +02:00
mediaManager . showGameOverlay ( ) ;
2021-05-19 11:17:43 +02:00
//receive message start
this . Connection . receiveWebrtcStart ( ( message : UserSimplePeerInterface ) = > {
this . receiveWebrtcStart ( message ) ;
2020-04-25 16:05:33 +02:00
} ) ;
2020-05-01 21:15:00 +02:00
2020-06-05 13:07:18 +02:00
this . Connection . disconnectMessage ( ( data : WebRtcDisconnectMessageInterface ) : void = > {
2020-05-24 23:14:12 +02:00
this . closeConnection ( data . userId ) ;
2020-05-02 20:46:02 +02:00
} ) ;
2020-04-25 16:05:33 +02:00
}
2021-02-02 18:19:51 +01:00
private receiveWebrtcStart ( user : UserSimplePeerInterface ) : void {
2020-09-29 16:01:22 +02:00
this . Users . push ( user ) ;
2020-08-20 00:05:00 +02:00
// 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)
2020-06-05 13:07:18 +02:00
// So we can receive a request we already had before. (which will abort at the first line of createPeerConnection)
// This would be symmetrical to the way we handle disconnection.
2021-02-16 09:58:08 +01:00
2020-05-24 23:14:12 +02:00
//start connection
2021-02-16 18:13:30 +01:00
//console.log('receiveWebrtcStart. Initiator: ', user.initiator)
2020-09-29 16:01:22 +02:00
if ( ! user . initiator ) {
return ;
}
2021-05-29 22:34:38 +02:00
const streamResult = get ( localStreamStore ) ;
let stream : MediaStream | null = null ;
if ( streamResult . type === 'success' && streamResult . stream ) {
stream = streamResult . stream ;
}
this . createPeerConnection ( user , stream ) ;
2020-04-25 16:05:33 +02:00
}
2020-05-02 20:46:02 +02:00
/ * *
2020-05-24 23:14:12 +02:00
* create peer connection to bind users
2020-05-02 20:46:02 +02:00
* /
2021-05-29 22:34:38 +02:00
private createPeerConnection ( user : UserSimplePeerInterface , localStream : MediaStream | null ) : VideoPeer | null {
2020-10-20 18:02:44 +02:00
const peerConnection = this . PeerConnectionArray . get ( user . userId )
2020-10-20 20:39:33 +02:00
if ( peerConnection ) {
if ( peerConnection . destroyed ) {
2020-10-20 18:02:44 +02:00
peerConnection . toClose = true ;
peerConnection . destroy ( ) ;
2020-10-20 18:03:10 +02:00
const peerConnexionDeleted = this . PeerConnectionArray . delete ( user . userId ) ;
2020-10-20 20:39:33 +02:00
if ( ! peerConnexionDeleted ) {
2020-10-20 18:02:44 +02:00
throw 'Error to delete peer connection' ;
}
2021-05-29 22:34:38 +02:00
//return this.createPeerConnection(user, localStream);
2020-10-20 20:39:33 +02:00
} else {
2020-10-20 18:02:44 +02:00
peerConnection . toClose = false ;
2021-05-29 22:34:38 +02:00
return null ;
2020-10-20 18:02:44 +02:00
}
2020-05-02 20:46:02 +02:00
}
2020-05-01 21:15:00 +02:00
2020-05-14 20:39:30 +02:00
let name = user . name ;
2020-10-20 20:39:33 +02:00
if ( ! name ) {
2020-06-08 09:20:36 +02:00
const userSearch = this . Users . find ( ( userSearch : UserSimplePeerInterface ) = > userSearch . userId === user . userId ) ;
2020-10-20 20:39:33 +02:00
if ( userSearch ) {
2020-05-14 20:39:30 +02:00
name = userSearch . name ;
}
}
2020-06-08 09:20:36 +02:00
2020-09-18 13:57:38 +02:00
mediaManager . removeActiveVideo ( "" + user . userId ) ;
2020-10-15 12:12:11 +02:00
2021-02-02 18:19:51 +01:00
mediaManager . addActiveVideo ( user , name ) ;
2020-05-02 20:46:02 +02:00
2021-02-18 11:52:30 +01:00
this . lastWebrtcUserName = user . webRtcUser ;
this . lastWebrtcPassword = user . webRtcPassword ;
2021-05-29 22:34:38 +02:00
const peer = new VideoPeer ( user , user . initiator ? user.initiator : false , this . Connection , localStream ) ;
2020-10-25 21:59:14 +01:00
//permit to send message
2020-10-26 14:13:51 +01:00
mediaManager . addSendMessageCallback ( user . userId , ( message : string ) = > {
2021-02-02 18:19:51 +01:00
peer . write ( new Buffer ( JSON . stringify ( { type : MESSAGE_TYPE_MESSAGE , name : this.myName.toUpperCase ( ) , userId : this.userId , message : message } ) ) ) ;
2020-10-25 21:59:14 +01:00
} ) ;
2020-10-20 18:02:44 +02:00
peer . toClose = false ;
2020-08-20 16:56:10 +02:00
// When a connection is established to a video stream, and if a screen sharing is taking place,
// the user sharing screen should also initiate a connection to the remote user!
2020-06-03 22:32:43 +02:00
peer . on ( 'connect' , ( ) = > {
2021-05-29 22:04:08 +02:00
const streamResult = get ( screenSharingLocalStreamStore ) ;
if ( streamResult . type === 'success' && streamResult . stream !== null ) {
this . sendLocalScreenSharingStreamToUser ( user . userId , streamResult . stream ) ;
2020-08-20 00:05:00 +02:00
}
2020-05-02 20:46:02 +02:00
} ) ;
2021-05-07 01:37:05 +02:00
//Create a notification for first user in circle discussion
if ( this . PeerConnectionArray . size === 0 ) {
mediaManager . createNotification ( user . name ? ? '' ) ;
}
2020-08-20 16:56:10 +02:00
this . PeerConnectionArray . set ( user . userId , peer ) ;
2020-05-02 20:46:02 +02:00
2020-08-20 16:56:10 +02:00
for ( const peerConnectionListener of this . peerConnectionListeners ) {
peerConnectionListener . onConnect ( user ) ;
}
return peer ;
}
2020-06-06 17:03:10 +02:00
2020-08-20 16:56:10 +02:00
/ * *
* create peer connection to bind users
* /
2021-05-29 22:04:08 +02:00
private createPeerScreenSharingConnection ( user : UserSimplePeerInterface , stream : MediaStream | null ) : ScreenSharingPeer | null {
2020-10-20 20:39:33 +02:00
const peerConnection = this . PeerScreenSharingConnectionArray . get ( user . userId ) ;
if ( peerConnection ) {
if ( peerConnection . destroyed ) {
peerConnection . toClose = true ;
peerConnection . destroy ( ) ;
const peerConnexionDeleted = this . PeerScreenSharingConnectionArray . delete ( user . userId ) ;
if ( ! peerConnexionDeleted ) {
throw 'Error to delete peer connection' ;
}
2021-05-29 22:34:38 +02:00
this . createPeerConnection ( user , stream ) ;
2020-10-20 20:39:33 +02:00
} else {
peerConnection . toClose = false ;
}
2020-08-20 16:56:10 +02:00
return null ;
}
2020-05-23 14:00:36 +02:00
2020-08-20 16:56:10 +02:00
// We should display the screen sharing ONLY if we are not initiator
if ( ! user . initiator ) {
2020-09-18 13:57:38 +02:00
mediaManager . removeActiveScreenSharingVideo ( "" + user . userId ) ;
mediaManager . addScreenSharingActiveVideo ( "" + user . userId ) ;
2020-06-11 23:18:06 +02:00
}
2020-08-17 16:12:53 +02:00
2021-02-18 11:52:30 +01:00
// Enrich the user with last known credentials (if they are not set in the user object, which happens when a user triggers the screen sharing)
if ( user . webRtcUser === undefined ) {
user . webRtcUser = this . lastWebrtcUserName ;
user . webRtcPassword = this . lastWebrtcPassword ;
}
2021-05-29 22:04:08 +02:00
const peer = new ScreenSharingPeer ( user , user . initiator ? user.initiator : false , this . Connection , stream ) ;
2020-08-20 16:56:10 +02:00
this . PeerScreenSharingConnectionArray . set ( user . userId , peer ) ;
2020-08-17 16:18:39 +02:00
for ( const peerConnectionListener of this . peerConnectionListeners ) {
2020-08-17 16:12:53 +02:00
peerConnectionListener . onConnect ( user ) ;
}
2020-06-08 09:20:36 +02:00
return peer ;
2020-04-26 19:12:01 +02:00
}
2020-06-05 13:07:18 +02:00
/ * *
* This is triggered twice . Once by the server , and once by a remote client disconnecting
* /
2020-09-18 13:57:38 +02:00
private closeConnection ( userId : number ) {
2020-12-11 15:35:13 +01:00
mediaManager . playWebrtcOutSound ( ) ;
2020-05-02 20:46:02 +02:00
try {
2020-06-09 23:13:26 +02:00
const peer = this . PeerConnectionArray . get ( userId ) ;
2020-06-05 13:07:18 +02:00
if ( peer === undefined ) {
2020-10-20 18:02:44 +02:00
console . warn ( "closeConnection => Tried to close connection for user " + userId + " but could not find user" ) ;
2020-05-02 20:46:02 +02:00
return ;
}
2020-10-20 18:02:44 +02:00
//create temp perr to close
peer . toClose = true ;
2020-08-20 22:23:22 +02:00
peer . destroy ( ) ;
2020-06-05 13:07:18 +02:00
// 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.
2020-10-20 18:02:44 +02:00
2020-06-14 14:47:16 +02:00
this . closeScreenSharingConnection ( userId ) ;
2020-10-20 18:02:44 +02:00
2020-11-27 14:51:50 +01:00
const userIndex = this . Users . findIndex ( user = > user . userId === userId ) ;
if ( userIndex < 0 ) {
throw 'Couln\'t delete user' ;
} else {
this . Users . splice ( userIndex , 1 ) ;
}
2020-05-02 20:46:02 +02:00
} catch ( err ) {
2020-05-24 23:14:12 +02:00
console . error ( "closeConnection" , err )
2020-05-02 20:46:02 +02:00
}
2021-01-07 12:58:45 +01:00
//if user left discussion, clear array peer connection of sharing
if ( this . Users . length === 0 ) {
for ( const userId of this . PeerScreenSharingConnectionArray . keys ( ) ) {
this . closeScreenSharingConnection ( userId ) ;
this . PeerScreenSharingConnectionArray . delete ( userId ) ;
}
}
2021-03-19 15:03:55 +01:00
for ( const peerConnectionListener of this . peerConnectionListeners ) {
peerConnectionListener . onDisconnect ( userId ) ;
}
2020-04-25 16:05:33 +02:00
}
2020-06-11 23:18:06 +02:00
/ * *
* This is triggered twice . Once by the server , and once by a remote client disconnecting
* /
2020-09-18 13:57:38 +02:00
private closeScreenSharingConnection ( userId : number ) {
2020-06-11 23:18:06 +02:00
try {
2020-09-18 13:57:38 +02:00
mediaManager . removeActiveScreenSharingVideo ( "" + userId ) ;
2020-08-18 14:59:50 +02:00
const peer = this . PeerScreenSharingConnectionArray . get ( userId ) ;
2020-06-11 23:18:06 +02:00
if ( peer === undefined ) {
2020-10-20 18:02:44 +02:00
console . warn ( "closeScreenSharingConnection => Tried to close connection for user " + userId + " but could not find user" )
2020-06-11 23:18:06 +02:00
return ;
}
// 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.
2020-08-20 22:23:22 +02:00
peer . destroy ( ) ;
2021-01-07 12:13:12 +01:00
//Comment this peer connexion because if we delete and try to reshare screen, the RTCPeerConnection send renegociate event. This array will be remove when user left circle discussion
/ * i f ( ! t h i s . P e e r S c r e e n S h a r i n g C o n n e c t i o n A r r a y . d e l e t e ( u s e r I d ) ) {
2020-10-20 14:48:59 +02:00
throw 'Couln\'t delete peer screen sharing connexion' ;
2021-01-07 12:13:12 +01:00
} * /
2020-06-11 23:18:06 +02:00
//console.log('Nb users in peerConnectionArray '+this.PeerConnectionArray.size);
} catch ( err ) {
console . error ( "closeConnection" , err )
}
}
2020-06-22 15:00:23 +02:00
public closeAllConnections() {
for ( const userId of this . PeerConnectionArray . keys ( ) ) {
this . closeConnection ( userId ) ;
}
2020-08-20 16:56:10 +02:00
for ( const userId of this . PeerScreenSharingConnectionArray . keys ( ) ) {
this . closeScreenSharingConnection ( userId ) ;
}
2020-06-22 15:00:23 +02:00
}
2020-06-23 14:56:57 +02:00
/ * *
* Unregisters any held event handler .
* /
public unregister() {
2021-05-29 22:04:08 +02:00
for ( const unsubscriber of this . unsubscribers ) {
unsubscriber ( ) ;
}
2020-06-23 14:56:57 +02:00
}
2020-06-19 16:36:40 +02:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2020-08-20 16:56:10 +02:00
private receiveWebrtcSignal ( data : WebRtcSignalReceivedMessageInterface ) {
2020-05-02 20:46:02 +02:00
try {
2020-05-24 23:14:12 +02:00
//if offer type, create peer connection
2020-05-02 20:46:02 +02:00
if ( data . signal . type === "offer" ) {
2021-05-29 22:34:38 +02:00
const streamResult = get ( localStreamStore ) ;
let stream : MediaStream | null = null ;
if ( streamResult . type === 'success' && streamResult . stream ) {
stream = streamResult . stream ;
}
this . createPeerConnection ( data , stream ) ;
2020-05-02 20:46:02 +02:00
}
2020-06-09 23:13:26 +02:00
const peer = this . PeerConnectionArray . get ( data . userId ) ;
2020-06-03 22:32:43 +02:00
if ( peer !== undefined ) {
peer . signal ( data . signal ) ;
} else {
console . error ( 'Could not find peer whose ID is "' + data . userId + '" in PeerConnectionArray' ) ;
}
2020-05-02 20:46:02 +02:00
} catch ( e ) {
console . error ( ` receiveWebrtcSignal => ${ data . userId } ` , e ) ;
2020-04-25 16:05:33 +02:00
}
}
2020-08-20 16:56:10 +02:00
private receiveWebrtcScreenSharingSignal ( data : WebRtcSignalReceivedMessageInterface ) {
2021-02-02 18:19:51 +01:00
if ( blackListManager . isBlackListed ( data . userId ) ) return ;
2020-06-11 23:18:06 +02:00
console . log ( "receiveWebrtcScreenSharingSignal" , data ) ;
2021-05-29 22:04:08 +02:00
const streamResult = get ( screenSharingLocalStreamStore ) ;
let stream : MediaStream | null = null ;
if ( streamResult . type === 'success' && streamResult . stream !== null ) {
stream = streamResult . stream ;
}
2020-06-11 23:18:06 +02:00
try {
//if offer type, create peer connection
if ( data . signal . type === "offer" ) {
2021-05-29 22:04:08 +02:00
this . createPeerScreenSharingConnection ( data , stream ) ;
2020-06-11 23:18:06 +02:00
}
2020-08-18 14:59:50 +02:00
const peer = this . PeerScreenSharingConnectionArray . get ( data . userId ) ;
2020-06-11 23:18:06 +02:00
if ( peer !== undefined ) {
peer . signal ( data . signal ) ;
} else {
2020-06-14 14:47:16 +02:00
console . error ( 'Could not find peer whose ID is "' + data . userId + '" in receiveWebrtcScreenSharingSignal' ) ;
2021-05-29 22:04:08 +02:00
console . info ( 'Attempt to create new peer connexion' ) ;
if ( stream ) {
this . sendLocalScreenSharingStreamToUser ( data . userId , stream ) ;
}
2020-06-11 23:18:06 +02:00
}
} catch ( e ) {
console . error ( ` receiveWebrtcSignal => ${ data . userId } ` , e ) ;
2021-01-07 12:13:12 +01:00
//Comment this peer connexion because if we delete and try to reshare screen, the RTCPeerConnection send renegociate event. This array will be remove when user left circle discussion
//this.PeerScreenSharingConnectionArray.delete(data.userId);
2020-10-20 14:48:59 +02:00
this . receiveWebrtcScreenSharingSignal ( data ) ;
2020-06-11 23:18:06 +02:00
}
}
2021-05-29 22:04:08 +02:00
private pushVideoToRemoteUser ( userId : number , streamResult : LocalStreamStoreValue ) {
2020-05-02 20:46:02 +02:00
try {
2020-08-18 14:59:50 +02:00
const PeerConnection = this . PeerConnectionArray . get ( userId ) ;
2020-06-08 22:52:25 +02:00
if ( ! PeerConnection ) {
2020-06-06 17:03:10 +02:00
throw new Error ( 'While adding media, cannot find user with ID ' + userId ) ;
2020-06-03 22:57:00 +02:00
}
2021-05-19 11:17:43 +02:00
2021-05-29 22:04:08 +02:00
PeerConnection . write ( new Buffer ( JSON . stringify ( { type : MESSAGE_TYPE_CONSTRAINT , . . . streamResult . constraints } ) ) ) ;
2021-05-19 11:17:43 +02:00
2021-05-29 22:04:08 +02:00
if ( streamResult . type === 'error' ) {
2021-05-19 11:17:43 +02:00
return ;
}
2021-05-29 22:04:08 +02:00
const localStream : MediaStream | null = streamResult . stream ;
2020-06-06 19:52:34 +02:00
2020-06-08 09:20:36 +02:00
if ( ! localStream ) {
return ;
}
2020-08-20 00:05:00 +02:00
for ( const track of localStream . getTracks ( ) ) {
2020-11-27 14:51:50 +01:00
//todo: this is a ugly hack to reduce the amount of error in console. Find a better way.
if ( ( track as any ) . added !== undefined ) continue ; // eslint-disable-line @typescript-eslint/no-explicit-any
( track as any ) . added = true ; // eslint-disable-line @typescript-eslint/no-explicit-any
2020-08-20 00:05:00 +02:00
PeerConnection . addTrack ( track , localStream ) ;
2020-06-03 22:57:00 +02:00
}
2020-05-02 20:46:02 +02:00
} catch ( e ) {
2020-08-20 00:05:00 +02:00
console . error ( ` pushVideoToRemoteUser => ${ userId } ` , e ) ;
2020-05-01 21:15:00 +02:00
}
2020-04-26 20:55:20 +02:00
}
2020-05-03 17:19:42 +02:00
2021-05-29 22:04:08 +02:00
private pushScreenSharingToRemoteUser ( userId : number , localScreenCapture : MediaStream ) {
2020-08-18 14:59:50 +02:00
const PeerConnection = this . PeerScreenSharingConnectionArray . get ( userId ) ;
2020-06-11 23:18:06 +02:00
if ( ! PeerConnection ) {
2020-08-20 00:05:00 +02:00
throw new Error ( 'While pushing screen sharing, cannot find user with ID ' + userId ) ;
2020-06-11 23:18:06 +02:00
}
2020-08-20 00:05:00 +02:00
for ( const track of localScreenCapture . getTracks ( ) ) {
2020-06-11 23:18:06 +02:00
PeerConnection . addTrack ( track , localScreenCapture ) ;
2020-08-20 00:05:00 +02:00
}
2020-06-11 23:18:06 +02:00
return ;
}
2021-05-29 22:04:08 +02:00
public sendLocalVideoStream ( streamResult : LocalStreamStoreValue ) {
2020-08-31 15:21:05 +02:00
for ( const user of this . Users ) {
2021-05-29 22:04:08 +02:00
this . pushVideoToRemoteUser ( user . userId , streamResult ) ;
2020-08-31 15:21:05 +02:00
}
2020-05-03 17:19:42 +02:00
}
2020-06-08 09:20:36 +02:00
2020-08-20 00:05:00 +02:00
/ * *
* Triggered locally when clicking on the screen sharing button
* /
2021-05-29 22:04:08 +02:00
public sendLocalScreenSharingStream ( localScreenCapture : MediaStream ) {
2020-08-21 22:53:17 +02:00
for ( const user of this . Users ) {
2021-05-29 22:04:08 +02:00
this . sendLocalScreenSharingStreamToUser ( user . userId , localScreenCapture ) ;
2020-08-21 22:53:17 +02:00
}
}
/ * *
* Triggered locally when clicking on the screen sharing button
* /
public stopLocalScreenSharingStream ( stream : MediaStream ) {
for ( const user of this . Users ) {
this . stopLocalScreenSharingStreamToUser ( user . userId , stream ) ;
2020-06-08 09:20:36 +02:00
}
}
2020-08-20 00:05:00 +02:00
2021-05-29 22:04:08 +02:00
private sendLocalScreenSharingStreamToUser ( userId : number , localScreenCapture : MediaStream ) : void {
2021-02-02 18:19:51 +01:00
if ( blackListManager . isBlackListed ( userId ) ) return ;
2020-08-20 00:05:00 +02:00
// 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 ) ) {
2021-05-29 22:04:08 +02:00
this . pushScreenSharingToRemoteUser ( userId , localScreenCapture ) ;
2020-08-20 00:05:00 +02:00
return ;
}
const screenSharingUser : UserSimplePeerInterface = {
userId ,
initiator : true
} ;
2021-05-29 22:04:08 +02:00
const PeerConnectionScreenSharing = this . createPeerScreenSharingConnection ( screenSharingUser , localScreenCapture ) ;
2020-08-20 00:05:00 +02:00
if ( ! PeerConnectionScreenSharing ) {
return ;
}
}
2020-09-18 13:57:38 +02:00
private stopLocalScreenSharingStreamToUser ( userId : number , stream : MediaStream ) : void {
2020-08-20 00:05:00 +02:00
const PeerConnectionScreenSharing = this . PeerScreenSharingConnectionArray . get ( userId ) ;
if ( ! PeerConnectionScreenSharing ) {
throw new Error ( 'Weird, screen sharing connection to user ' + userId + 'not found' )
}
console . log ( "updatedScreenSharing => destroy" , PeerConnectionScreenSharing ) ;
2020-08-21 22:53:17 +02:00
// Stop sending stream and close peer connection if peer is not sending stream too
PeerConnectionScreenSharing . stopPushingScreenSharingToRemoteUser ( stream ) ;
if ( ! PeerConnectionScreenSharing . isReceivingScreenSharingStream ( ) ) {
PeerConnectionScreenSharing . destroy ( ) ;
2021-01-07 12:13:12 +01:00
//Comment this peer connexion because if we delete and try to reshare screen, the RTCPeerConnection send renegociate event. This array will be remove when user left circle discussion
//this.PeerScreenSharingConnectionArray.delete(userId);
2020-08-21 22:53:17 +02:00
}
2020-08-20 00:05:00 +02:00
}
2020-05-14 22:00:31 +02:00
}