c28108f6 |
1 | import {ConnexionInterface} from "../Connexion"; |
2 | import {MediaManager} from "./MediaManager"; |
3 | let Peer = require('simple-peer'); |
4 | |
787e1c46 |
5 | class UserSimplePear{ |
6 | userId: string; |
7 | name?: string; |
8 | initiator?: boolean; |
70793172 |
9 | } |
787e1c46 |
10 | export class SimplePeerInterface {} |
11 | export class SimplePeer implements SimplePeerInterface{ |
e06b20fe |
12 | private Connexion: ConnexionInterface; |
e06b20fe |
13 | private WebRtcRoomId: string; |
787e1c46 |
14 | private Users: Array<UserSimplePear> = new Array<UserSimplePear>(); |
e06b20fe |
15 | |
fdb40ec3 |
16 | private MediaManager: MediaManager; |
c28108f6 |
17 | |
787e1c46 |
18 | private PeerConnexionArray: Map<string, any> = new Map<string, any>(); |
c28108f6 |
19 | |
58df4118 |
20 | constructor(Connexion: ConnexionInterface, WebRtcRoomId: string = "test-webrtc") { |
c28108f6 |
21 | this.Connexion = Connexion; |
58df4118 |
22 | this.WebRtcRoomId = WebRtcRoomId; |
fb255140 |
23 | this.MediaManager = new MediaManager((stream : MediaStream) => { |
24 | this.updatedLocalStream(); |
25 | }); |
2bfa57b0 |
26 | this.initialise(); |
27 | } |
28 | |
29 | /** |
30 | * permit to listen when user could start visio |
31 | */ |
fdb40ec3 |
32 | private initialise() { |
c28108f6 |
33 | |
e06b20fe |
34 | //receive signal by gemer |
35 | this.Connexion.receiveWebrtcSignal((message: string) => { |
36 | this.receiveWebrtcSignal(message); |
37 | }); |
c28108f6 |
38 | |
fdb40ec3 |
39 | this.MediaManager.activeVisio(); |
40 | this.MediaManager.getCamera().then(() => { |
41 | |
42 | //receive message start |
43 | this.Connexion.receiveWebrtcStart((message: string) => { |
44 | this.receiveWebrtcStart(message); |
45 | }); |
46 | |
47 | }).catch((err) => { |
48 | console.error("err", err); |
c28108f6 |
49 | }); |
e06b20fe |
50 | |
fdb40ec3 |
51 | //receive signal by gemer |
52 | this.Connexion.disconnectMessage((message: string) => { |
53 | let data = JSON.parse(message); |
54 | this.closeConnexion(data.userId); |
55 | }); |
c28108f6 |
56 | } |
57 | |
58 | /** |
59 | * |
e4a30712 |
60 | * @param message |
c28108f6 |
61 | */ |
e06b20fe |
62 | private receiveWebrtcStart(message: string) { |
c28108f6 |
63 | let data = JSON.parse(message); |
58df4118 |
64 | this.WebRtcRoomId = data.roomId; |
2bfa57b0 |
65 | this.Users = data.clients; |
c28108f6 |
66 | |
e06b20fe |
67 | //start connexion |
68 | this.startWebRtc(); |
c28108f6 |
69 | } |
70 | |
fdb40ec3 |
71 | /** |
72 | * server has two person connected, start the meet |
73 | */ |
74 | private startWebRtc() { |
787e1c46 |
75 | this.Users.forEach((user: UserSimplePear) => { |
fdb40ec3 |
76 | //if it's not an initiator, peer connexion will be created when gamer will receive offer signal |
77 | if(!user.initiator){ |
89db8558 |
78 | return; |
79 | } |
fdb40ec3 |
80 | this.createPeerConnexion(user); |
81 | }); |
82 | } |
575054fe |
83 | |
fdb40ec3 |
84 | /** |
85 | * create peer connexion to bind users |
86 | */ |
787e1c46 |
87 | private createPeerConnexion(user : UserSimplePear) { |
88 | if(this.PeerConnexionArray.has(user.userId)) { |
fdb40ec3 |
89 | return; |
90 | } |
e06b20fe |
91 | |
787e1c46 |
92 | let name = user.name; |
93 | if(!name){ |
94 | let userSearch = this.Users.find((userSearch: UserSimplePear) => userSearch.userId === user.userId); |
95 | if(userSearch) { |
96 | name = userSearch.name; |
97 | } |
98 | } |
fdb40ec3 |
99 | this.MediaManager.removeActiveVideo(user.userId); |
787e1c46 |
100 | this.MediaManager.addActiveVideo(user.userId, name); |
fdb40ec3 |
101 | |
787e1c46 |
102 | let peer : any = new Peer({ |
fdb40ec3 |
103 | initiator: user.initiator ? user.initiator : false, |
104 | reconnectTimer: 10000, |
105 | config: { |
106 | iceServers: [ |
107 | { |
108 | urls: 'stun:stun.l.google.com:19302' |
109 | }, |
110 | { |
111 | urls: 'turn:numb.viagenie.ca', |
112 | username: 'g.parant@thecodingmachine.com', |
fb255140 |
113 | credential: 'itcugcOHxle9Acqi$' |
fdb40ec3 |
114 | }, |
115 | ] |
116 | }, |
117 | }); |
787e1c46 |
118 | this.PeerConnexionArray.set(user.userId, peer); |
89db8558 |
119 | |
fdb40ec3 |
120 | //start listen signal for the peer connexion |
787e1c46 |
121 | this.PeerConnexionArray.get(user.userId).on('signal', (data: any) => { |
fdb40ec3 |
122 | this.sendWebrtcSignal(data, user.userId); |
123 | }); |
c28108f6 |
124 | |
787e1c46 |
125 | this.PeerConnexionArray.get(user.userId).on('stream', (stream: MediaStream) => { |
126 | let videoActive = false; |
127 | let microphoneActive = false; |
128 | stream.getTracks().forEach((track : MediaStreamTrack) => { |
129 | if(track.kind === "audio"){ |
130 | microphoneActive = true; |
131 | } |
132 | if(track.kind === "video"){ |
133 | videoActive = true; |
134 | } |
135 | }); |
136 | if(microphoneActive){ |
137 | this.MediaManager.enabledMicrophoneByUserId(user.userId); |
138 | }else{ |
139 | this.MediaManager.disabledMicrophoneByUserId(user.userId); |
140 | } |
141 | |
142 | if(videoActive){ |
143 | this.MediaManager.enabledVideoByUserId(user.userId); |
144 | }else{ |
145 | this.MediaManager.disabledVideoByUserId(user.userId); |
146 | } |
fdb40ec3 |
147 | this.stream(user.userId, stream); |
148 | }); |
c28108f6 |
149 | |
787e1c46 |
150 | this.PeerConnexionArray.get(user.userId).on('track', (track: MediaStreamTrack, stream: MediaStream) => { |
fdb40ec3 |
151 | this.stream(user.userId, stream); |
152 | }); |
153 | |
787e1c46 |
154 | this.PeerConnexionArray.get(user.userId).on('close', () => { |
fdb40ec3 |
155 | this.closeConnexion(user.userId); |
156 | }); |
d7d7be9e |
157 | |
787e1c46 |
158 | this.PeerConnexionArray.get(user.userId).on('error', (err: any) => { |
fdb40ec3 |
159 | console.error(`error => ${user.userId} => ${err.code}`, err); |
c28108f6 |
160 | }); |
fdb40ec3 |
161 | |
787e1c46 |
162 | this.PeerConnexionArray.get(user.userId).on('connect', () => { |
fdb40ec3 |
163 | console.info(`connect => ${user.userId}`); |
164 | }); |
165 | |
166 | this.addMedia(user.userId); |
d7d7be9e |
167 | } |
168 | |
fdb40ec3 |
169 | private closeConnexion(userId : string) { |
170 | try { |
171 | this.MediaManager.removeActiveVideo(userId); |
787e1c46 |
172 | if (!this.PeerConnexionArray.get(userId)) { |
fdb40ec3 |
173 | return; |
174 | } |
175 | // @ts-ignore |
787e1c46 |
176 | this.PeerConnexionArray.get(userId).destroy(); |
177 | this.PeerConnexionArray.delete(userId) |
fdb40ec3 |
178 | } catch (err) { |
179 | console.error("closeConnexion", err) |
180 | } |
c28108f6 |
181 | } |
182 | |
183 | /** |
e4a30712 |
184 | * |
185 | * @param userId |
c28108f6 |
186 | * @param data |
187 | */ |
e06b20fe |
188 | private sendWebrtcSignal(data: any, userId : string) { |
fdb40ec3 |
189 | try { |
190 | this.Connexion.sendWebrtcSignal(data, this.WebRtcRoomId, null, userId); |
191 | }catch (e) { |
192 | console.error(`sendWebrtcSignal => ${userId}`, e); |
193 | } |
c28108f6 |
194 | } |
195 | |
196 | /** |
197 | * |
198 | * @param message |
199 | */ |
e06b20fe |
200 | private receiveWebrtcSignal(message: string) { |
c28108f6 |
201 | let data = JSON.parse(message); |
fdb40ec3 |
202 | try { |
203 | //if offer type, create peer connexion |
204 | if(data.signal.type === "offer"){ |
205 | this.createPeerConnexion(data); |
206 | } |
787e1c46 |
207 | this.PeerConnexionArray.get(data.userId).signal(data.signal); |
fdb40ec3 |
208 | } catch (e) { |
209 | console.error(`receiveWebrtcSignal => ${data.userId}`, e); |
c28108f6 |
210 | } |
c28108f6 |
211 | } |
212 | |
213 | /** |
575054fe |
214 | * |
215 | * @param userId |
c28108f6 |
216 | * @param stream |
217 | */ |
e06b20fe |
218 | private stream(userId : any, stream: MediaStream) { |
fdb40ec3 |
219 | this.MediaManager.addStreamRemoteVideo(userId, stream); |
c28108f6 |
220 | } |
221 | |
222 | /** |
575054fe |
223 | * |
224 | * @param userId |
c28108f6 |
225 | */ |
e06b20fe |
226 | private addMedia (userId : any = null) { |
fdb40ec3 |
227 | try { |
228 | let transceiver : any = null; |
787e1c46 |
229 | if(!this.MediaManager.localStream){ |
230 | return; |
231 | } |
fdb40ec3 |
232 | this.MediaManager.localStream.getTracks().forEach( |
787e1c46 |
233 | transceiver = (track: MediaStreamTrack) => this.PeerConnexionArray.get(userId).addTrack(track, this.MediaManager.localStream) |
fdb40ec3 |
234 | ) |
235 | }catch (e) { |
236 | console.error(`addMedia => addMedia => ${userId}`, e); |
e06b20fe |
237 | } |
b49c0123 |
238 | } |
fb255140 |
239 | |
240 | updatedLocalStream(){ |
787e1c46 |
241 | this.Users.forEach((user: UserSimplePear) => { |
fb255140 |
242 | this.addMedia(user.userId); |
243 | }) |
244 | } |
34d3a292 |
245 | } |