mitmi 1.1.7 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/dist/Conference.d.ts +54 -0
- package/dist/Contact.d.ts +20 -1
- package/dist/Session.d.ts +17 -0
- package/dist/Stream.d.ts +48 -15
- package/dist/core/SocketInteraction.d.ts +95 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/mitmi.d.ts +145 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/utils.d.ts +5 -5
- package/docs/.nojekyll +1 -0
- package/docs/assets/hierarchy.js +1 -0
- package/docs/assets/highlight.css +36 -0
- package/docs/assets/icons.js +18 -0
- package/docs/assets/icons.svg +1 -0
- package/docs/assets/main.js +60 -0
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1633 -0
- package/docs/classes/Conference.html +33 -0
- package/docs/classes/Contact.html +10 -0
- package/docs/classes/DeviceManager.html +9 -0
- package/docs/classes/HelloWorld.html +3 -0
- package/docs/classes/Session.html +12 -0
- package/docs/classes/Stream.html +46 -0
- package/docs/hierarchy.html +1 -0
- package/docs/index.html +35 -0
- package/docs/interfaces/ContactInfo.html +4 -0
- package/docs/interfaces/StreamParams.html +4 -0
- package/docs/modules.html +1 -0
- package/package.json +7 -5
- package/src/Conference.ts +55 -0
- package/src/Contact.ts +20 -1
- package/src/Session.ts +17 -0
- package/src/Stream.ts +72 -38
- package/src/core/SocketInteraction.ts +107 -2
- package/src/index.ts +4 -0
- package/src/utils.ts +12 -6
package/src/Stream.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { Conference } from "./Conference";
|
|
2
2
|
import { setLocalStream } from "./utils";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Stream constraints
|
|
6
|
+
*/
|
|
4
7
|
export interface StreamParams {
|
|
5
8
|
audio: boolean;
|
|
6
9
|
video: boolean;
|
|
7
10
|
}
|
|
8
11
|
|
|
12
|
+
/**
|
|
13
|
+
* This class represent a video, camera or screenshare.
|
|
14
|
+
*/
|
|
9
15
|
class Stream {
|
|
10
16
|
mediastream: MediaStream;
|
|
11
17
|
domElement: undefined | HTMLVideoElement;
|
|
@@ -17,10 +23,14 @@ class Stream {
|
|
|
17
23
|
params: StreamParams;
|
|
18
24
|
|
|
19
25
|
/**
|
|
26
|
+
* Create a Stream
|
|
27
|
+
*
|
|
28
|
+
* @param mediastream - The video input to attach to the stream
|
|
29
|
+
* @param ownerId - The ownerId of the mediastream
|
|
30
|
+
* @param ownerName - The owner of the mediastream
|
|
20
31
|
*
|
|
21
|
-
* @param mediastream
|
|
22
|
-
* @param owner "" => ourself, id instead
|
|
23
32
|
*/
|
|
33
|
+
//TODO Enlever le fait que ownerid est une string vide si l'owner est soit meme
|
|
24
34
|
constructor(mediastream: MediaStream, ownerId: string, ownerName: string) {
|
|
25
35
|
this.mediastream = mediastream;
|
|
26
36
|
this.ownerId = ownerId;
|
|
@@ -29,15 +39,24 @@ class Stream {
|
|
|
29
39
|
this.params = { audio: true, video: false };
|
|
30
40
|
}
|
|
31
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Check if the stream is local
|
|
44
|
+
*
|
|
45
|
+
* @returns - True if it's a localstream, false instead
|
|
46
|
+
*/
|
|
32
47
|
isLocal(): boolean {
|
|
33
48
|
return this.ownerId === "";
|
|
34
49
|
}
|
|
35
50
|
|
|
36
51
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* @param
|
|
40
|
-
* @
|
|
52
|
+
* Get camera input
|
|
53
|
+
*
|
|
54
|
+
* @param video - Is video enable ?
|
|
55
|
+
* @param audio - Is audio enable ?
|
|
56
|
+
* @param audioDeviceId optional - Use a specific audio device
|
|
57
|
+
* @param videoDeviceId optional - Use a specific video device
|
|
58
|
+
*
|
|
59
|
+
* @returns A stream with your camera.
|
|
41
60
|
*/
|
|
42
61
|
static async getCamera(
|
|
43
62
|
video: boolean,
|
|
@@ -65,82 +84,97 @@ class Stream {
|
|
|
65
84
|
}
|
|
66
85
|
static getScreen() {}
|
|
67
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Attach the stream to your DOM
|
|
89
|
+
*
|
|
90
|
+
* @param domElement - The HTML element to attach the stream
|
|
91
|
+
*/
|
|
68
92
|
attachToElement(domElement: HTMLVideoElement): void {
|
|
69
93
|
this.domElement = domElement;
|
|
70
94
|
domElement.srcObject = this.mediastream;
|
|
71
95
|
|
|
72
96
|
if (this.isLocal()) {
|
|
73
|
-
this.
|
|
97
|
+
this.localMuteAudio();
|
|
74
98
|
}
|
|
75
99
|
}
|
|
76
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Detach the stream to your DOM
|
|
103
|
+
*/
|
|
77
104
|
detachToElement(): void {
|
|
78
105
|
if (!this.domElement) return;
|
|
79
106
|
this.domElement.srcObject = null;
|
|
80
107
|
}
|
|
81
108
|
|
|
82
|
-
|
|
83
|
-
* If the stream is published (so its yours) :
|
|
84
|
-
* - video will be disabled for everyone
|
|
85
|
-
* If the stream is not published (its yours but not publish, or other ppl stream):
|
|
86
|
-
* - video will be disabled for you only
|
|
87
|
-
*/
|
|
88
|
-
muteVideo() {
|
|
89
|
-
this.params.video = false;
|
|
109
|
+
globalMuteVideo() {
|
|
90
110
|
if (this.conferencePublish) {
|
|
91
|
-
|
|
92
|
-
this.conferencePublish.session.socketInteraction.setConstraint(this);
|
|
111
|
+
this.params.video = false;
|
|
112
|
+
//this.conferencePublish.session.socketInteraction.setConstraint(this);
|
|
113
|
+
this.mediastream.getVideoTracks()[0].enabled = false;
|
|
93
114
|
}
|
|
94
|
-
this.mediastream.getVideoTracks()[0].enabled = false;
|
|
95
115
|
}
|
|
96
116
|
|
|
97
|
-
|
|
98
|
-
this.params.video = true;
|
|
117
|
+
globalUnmuteVideo() {
|
|
99
118
|
if (this.conferencePublish) {
|
|
100
|
-
|
|
101
|
-
this.conferencePublish.session.socketInteraction.setConstraint(this);
|
|
119
|
+
this.params.video = true;
|
|
120
|
+
//this.conferencePublish.session.socketInteraction.setConstraint(this);
|
|
121
|
+
this.mediastream.getVideoTracks()[0].enabled = true;
|
|
102
122
|
}
|
|
103
|
-
this.mediastream.getVideoTracks()[0].enabled = true;
|
|
104
123
|
}
|
|
105
124
|
|
|
106
|
-
|
|
107
|
-
this.params.audio = false;
|
|
125
|
+
globalMuteAudio(): void {
|
|
108
126
|
if (this.conferencePublish) {
|
|
109
|
-
this.
|
|
127
|
+
this.params.audio = false;
|
|
128
|
+
//this.conferencePublish.session.socketInteraction.setConstraint(this);
|
|
129
|
+
this.mediastream.getAudioTracks()[0].enabled = false;
|
|
110
130
|
}
|
|
111
|
-
this.mediastream.getAudioTracks()[0].enabled = false;
|
|
112
131
|
}
|
|
113
132
|
|
|
114
|
-
|
|
115
|
-
this.params.audio = true;
|
|
133
|
+
globalUnmuteAudio(): void {
|
|
116
134
|
if (this.conferencePublish) {
|
|
117
|
-
this.
|
|
135
|
+
this.params.audio = true;
|
|
136
|
+
//this.conferencePublish.session.socketInteraction.setConstraint(this);
|
|
137
|
+
this.mediastream.getAudioTracks()[0].enabled = true;
|
|
118
138
|
}
|
|
119
|
-
this.mediastream.getAudioTracks()[0].enabled = true;
|
|
120
139
|
}
|
|
121
140
|
|
|
122
141
|
/**
|
|
123
|
-
*
|
|
124
|
-
* You need to call here when a localstream is started.
|
|
142
|
+
* Disable local audio
|
|
125
143
|
*/
|
|
126
|
-
|
|
144
|
+
localMuteAudio(): void {
|
|
127
145
|
if (!this.domElement) return;
|
|
128
146
|
|
|
129
|
-
// Important: cette ligne n'affecte pas l'envoi audio
|
|
130
147
|
this.domElement.muted = true;
|
|
131
148
|
this.domElement.volume = 0;
|
|
132
149
|
}
|
|
133
150
|
|
|
134
151
|
/**
|
|
135
|
-
*
|
|
152
|
+
* Enable local audio
|
|
136
153
|
*/
|
|
137
|
-
|
|
154
|
+
localUnmuteAudio(): void {
|
|
138
155
|
if (!this.domElement) return;
|
|
139
156
|
|
|
140
|
-
// Important: cette ligne n'affecte pas l'envoi audio
|
|
141
157
|
this.domElement.muted = false;
|
|
142
158
|
this.domElement.volume = 1;
|
|
143
159
|
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Disable local video
|
|
163
|
+
*/
|
|
164
|
+
localMuteVideo(): void {
|
|
165
|
+
if (!this.domElement) return;
|
|
166
|
+
|
|
167
|
+
this.domElement.pause();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Enable local video
|
|
172
|
+
*/
|
|
173
|
+
async localUnmuteVideo(): Promise<void> {
|
|
174
|
+
if (!this.domElement) return;
|
|
175
|
+
|
|
176
|
+
await this.domElement.play();
|
|
177
|
+
}
|
|
144
178
|
}
|
|
145
179
|
|
|
146
180
|
export { Stream };
|
|
@@ -2,8 +2,11 @@ import { io, Socket } from "socket.io-client";
|
|
|
2
2
|
import { serverUrl } from "../constants";
|
|
3
3
|
import { getCurrentSession } from "../utils";
|
|
4
4
|
import { Stream, StreamParams } from "../Stream";
|
|
5
|
-
import { ContactInfo } from "../
|
|
5
|
+
import { ContactInfo } from "../Contact";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Type of message between server and client
|
|
9
|
+
*/
|
|
7
10
|
interface SocketMessage {
|
|
8
11
|
from: ContactInfo;
|
|
9
12
|
target?: string;
|
|
@@ -16,6 +19,12 @@ interface SocketMessage {
|
|
|
16
19
|
};
|
|
17
20
|
}
|
|
18
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Main interaction between socket and server
|
|
24
|
+
*
|
|
25
|
+
* @private
|
|
26
|
+
*
|
|
27
|
+
*/
|
|
19
28
|
export class SocketInteraction extends EventTarget {
|
|
20
29
|
private socket!: Socket;
|
|
21
30
|
private _userId?: string;
|
|
@@ -45,6 +54,12 @@ export class SocketInteraction extends EventTarget {
|
|
|
45
54
|
return this._userId;
|
|
46
55
|
}
|
|
47
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Publish a Stream into all peers
|
|
59
|
+
*
|
|
60
|
+
* @param stream - Stream to publish
|
|
61
|
+
*/
|
|
62
|
+
//TODO Check to publish multiple stream, ATM => one at the moment
|
|
48
63
|
publish(stream: Stream) {
|
|
49
64
|
this.localStream = stream;
|
|
50
65
|
|
|
@@ -55,6 +70,11 @@ export class SocketInteraction extends EventTarget {
|
|
|
55
70
|
console.log("[RTC] Stream published to all peers");
|
|
56
71
|
}
|
|
57
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Unbuplish stream into all peers
|
|
75
|
+
*
|
|
76
|
+
* @param stream - Stream to unpublish
|
|
77
|
+
*/
|
|
58
78
|
unpublish(stream: Stream) {
|
|
59
79
|
if (this.localStream != stream) throw new Error("this is not your stream");
|
|
60
80
|
this.localStream = undefined;
|
|
@@ -67,8 +87,10 @@ export class SocketInteraction extends EventTarget {
|
|
|
67
87
|
}
|
|
68
88
|
|
|
69
89
|
/**
|
|
90
|
+
* Set constraint to you stream ex : muteAudio
|
|
91
|
+
* Stream have stream.params, use to set constraint on the peer
|
|
70
92
|
*
|
|
71
|
-
* @param stream
|
|
93
|
+
* @param stream - Affected Stream with constraints
|
|
72
94
|
*/
|
|
73
95
|
setConstraint(stream: Stream) {
|
|
74
96
|
if (this.localStream != stream) throw new Error("this is not your stream");
|
|
@@ -91,6 +113,13 @@ export class SocketInteraction extends EventTarget {
|
|
|
91
113
|
console.log("[RTC] Set constraint");
|
|
92
114
|
}
|
|
93
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Attach a stream to a peer
|
|
118
|
+
*
|
|
119
|
+
* @param pc - PeerConnection to attach this.localstream
|
|
120
|
+
* @returns
|
|
121
|
+
*/
|
|
122
|
+
//TODO don't use this.localstream, but a parameter instead ?
|
|
94
123
|
private attachStreamToPeer(pc: RTCPeerConnection) {
|
|
95
124
|
if (!this.localStream) return;
|
|
96
125
|
|
|
@@ -100,6 +129,13 @@ export class SocketInteraction extends EventTarget {
|
|
|
100
129
|
});
|
|
101
130
|
}
|
|
102
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Detach a stream to a peer
|
|
134
|
+
*
|
|
135
|
+
* @param pc - PeerConnection to detach this.localstream
|
|
136
|
+
* @returns
|
|
137
|
+
*/
|
|
138
|
+
//TODO don't use this.localstream, but a parameter instead ?
|
|
103
139
|
private removeStreamToPeer(pc: RTCPeerConnection) {
|
|
104
140
|
if (!this.localStream) return;
|
|
105
141
|
|
|
@@ -108,6 +144,13 @@ export class SocketInteraction extends EventTarget {
|
|
|
108
144
|
});
|
|
109
145
|
}
|
|
110
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Stop sending a specific track
|
|
149
|
+
*
|
|
150
|
+
* @param pc - Affected Peerconnection
|
|
151
|
+
* @param track - Track to disable
|
|
152
|
+
* @returns
|
|
153
|
+
*/
|
|
111
154
|
private disableTrackToPeer(pc: RTCPeerConnection, track: MediaStreamTrack) {
|
|
112
155
|
if (!this.localStream) return;
|
|
113
156
|
|
|
@@ -120,6 +163,13 @@ export class SocketInteraction extends EventTarget {
|
|
|
120
163
|
});
|
|
121
164
|
}
|
|
122
165
|
|
|
166
|
+
/**
|
|
167
|
+
* Activate a track into a peer
|
|
168
|
+
*
|
|
169
|
+
* @param pc - Affected Peerconnection
|
|
170
|
+
* @param track - Track to enable
|
|
171
|
+
* @returns
|
|
172
|
+
*/
|
|
123
173
|
private enableTrackToPeer(pc: RTCPeerConnection, track: MediaStreamTrack) {
|
|
124
174
|
if (!this.localStream) return;
|
|
125
175
|
|
|
@@ -132,6 +182,11 @@ export class SocketInteraction extends EventTarget {
|
|
|
132
182
|
});
|
|
133
183
|
}
|
|
134
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Send a join message to the server
|
|
187
|
+
*
|
|
188
|
+
* @param confId - ID conference
|
|
189
|
+
*/
|
|
135
190
|
register(confId: number) {
|
|
136
191
|
/*if (!this.publishStream) {
|
|
137
192
|
throw new Error("Call publish() before register()");
|
|
@@ -147,7 +202,15 @@ export class SocketInteraction extends EventTarget {
|
|
|
147
202
|
console.log(`[CONF] Join request sent for room ${confId}`);
|
|
148
203
|
}
|
|
149
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Disconnect
|
|
207
|
+
*/
|
|
150
208
|
unregister() {
|
|
209
|
+
//Stop all the track before (release camera and microphone)
|
|
210
|
+
if (this.localStream) {
|
|
211
|
+
this.localStream.mediastream.getTracks().forEach((track) => track.stop());
|
|
212
|
+
}
|
|
213
|
+
|
|
151
214
|
Object.values(this.peerConnections).forEach((pc) => pc.close());
|
|
152
215
|
this.peerConnections = {};
|
|
153
216
|
|
|
@@ -157,6 +220,11 @@ export class SocketInteraction extends EventTarget {
|
|
|
157
220
|
console.log("[CONF] Unregistered and socket closed");
|
|
158
221
|
}
|
|
159
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Set Listeners
|
|
225
|
+
*
|
|
226
|
+
* @private
|
|
227
|
+
*/
|
|
160
228
|
private setupSocketListeners() {
|
|
161
229
|
this.socket.on("message", async (message: SocketMessage) => {
|
|
162
230
|
if (!this._confId) return;
|
|
@@ -199,6 +267,13 @@ export class SocketInteraction extends EventTarget {
|
|
|
199
267
|
});
|
|
200
268
|
}
|
|
201
269
|
|
|
270
|
+
/**
|
|
271
|
+
* Create a Peerconnection with the remote contact
|
|
272
|
+
*
|
|
273
|
+
* @param from - Peerconnection with this contact
|
|
274
|
+
* @param initiator - Are you the applicant
|
|
275
|
+
* @returns
|
|
276
|
+
*/
|
|
202
277
|
private async createPeerConnection(from: ContactInfo, initiator: boolean) {
|
|
203
278
|
const remoteUserId = from.id;
|
|
204
279
|
const remoteUserName = from.name;
|
|
@@ -249,6 +324,12 @@ export class SocketInteraction extends EventTarget {
|
|
|
249
324
|
}
|
|
250
325
|
}
|
|
251
326
|
|
|
327
|
+
/**
|
|
328
|
+
* Event handle the offer
|
|
329
|
+
*
|
|
330
|
+
* @param from - Contact who send the offer
|
|
331
|
+
* @param sdp - Offer
|
|
332
|
+
*/
|
|
252
333
|
private async handleOffer(from: ContactInfo, sdp: RTCSessionDescriptionInit) {
|
|
253
334
|
const remoteUserId = from.id;
|
|
254
335
|
await this.createPeerConnection(from, false);
|
|
@@ -277,6 +358,13 @@ export class SocketInteraction extends EventTarget {
|
|
|
277
358
|
this.dispatchEvent(event);
|
|
278
359
|
}
|
|
279
360
|
|
|
361
|
+
/**
|
|
362
|
+
* Event handle the enswer
|
|
363
|
+
*
|
|
364
|
+
* @param from - Contact who send tjhe answer
|
|
365
|
+
* @param sdp - The answer
|
|
366
|
+
* @returns
|
|
367
|
+
*/
|
|
280
368
|
private async handleAnswer(
|
|
281
369
|
from: ContactInfo,
|
|
282
370
|
sdp: RTCSessionDescriptionInit
|
|
@@ -294,6 +382,13 @@ export class SocketInteraction extends EventTarget {
|
|
|
294
382
|
this.dispatchEvent(event);
|
|
295
383
|
}
|
|
296
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Event when receive ice candidates
|
|
387
|
+
*
|
|
388
|
+
* @param from - Contact
|
|
389
|
+
* @param candidate - Icecandidate
|
|
390
|
+
* @returns
|
|
391
|
+
*/
|
|
297
392
|
private async handleIce(from: ContactInfo, candidate: RTCIceCandidate) {
|
|
298
393
|
const remoteUserId = from.id;
|
|
299
394
|
const pc = this.peerConnections[remoteUserId];
|
|
@@ -302,11 +397,21 @@ export class SocketInteraction extends EventTarget {
|
|
|
302
397
|
await pc.addIceCandidate(candidate);
|
|
303
398
|
}
|
|
304
399
|
|
|
400
|
+
/**
|
|
401
|
+
* Event when receive a disconnection message
|
|
402
|
+
*
|
|
403
|
+
* @param remoteId - ID that leave
|
|
404
|
+
*/
|
|
305
405
|
private removePeer(remoteId: string) {
|
|
306
406
|
this.peerConnections[remoteId]?.close();
|
|
307
407
|
delete this.peerConnections[remoteId];
|
|
308
408
|
}
|
|
309
409
|
|
|
410
|
+
/**
|
|
411
|
+
* Send a message on the socket
|
|
412
|
+
*
|
|
413
|
+
* @param msg - Message to send on the socket
|
|
414
|
+
*/
|
|
310
415
|
private sendMessage(msg: SocketMessage) {
|
|
311
416
|
this.socket.emit("message", msg);
|
|
312
417
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,3 +4,7 @@ export { HelloWorld } from "./HelloWorld";
|
|
|
4
4
|
export { Stream } from "./Stream";
|
|
5
5
|
export { Conference } from "./Conference";
|
|
6
6
|
export { DeviceManager } from "./DeviceManager";
|
|
7
|
+
|
|
8
|
+
//Interfaces
|
|
9
|
+
export type { StreamParams } from "./Stream";
|
|
10
|
+
export type { ContactInfo } from "./Contact";
|
package/src/utils.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { Session } from "./Session";
|
|
2
2
|
import { Stream } from "./Stream";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Generate a random string
|
|
6
|
+
*
|
|
7
|
+
* @returns - A random string format, ex: de0b1c44-b42e-c617-bcc2-14586c5fffe2
|
|
8
|
+
*/
|
|
4
9
|
function uidGenerator(): String {
|
|
5
10
|
var S4 = function () {
|
|
6
11
|
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
|
@@ -21,6 +26,9 @@ function uidGenerator(): String {
|
|
|
21
26
|
);
|
|
22
27
|
}
|
|
23
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Function for global session
|
|
31
|
+
*/
|
|
24
32
|
let currentSession: Session | undefined = undefined;
|
|
25
33
|
function setCurrentSession(newSession: undefined | Session) {
|
|
26
34
|
currentSession = newSession;
|
|
@@ -29,6 +37,10 @@ function getCurrentSession() {
|
|
|
29
37
|
return currentSession;
|
|
30
38
|
}
|
|
31
39
|
|
|
40
|
+
//TODO Useless ?
|
|
41
|
+
/**
|
|
42
|
+
* Function for localstream
|
|
43
|
+
*/
|
|
32
44
|
let localStream: Stream | undefined = undefined;
|
|
33
45
|
function setLocalStream(newStream: undefined | Stream) {
|
|
34
46
|
localStream = newStream;
|
|
@@ -37,12 +49,6 @@ function getLocalStream() {
|
|
|
37
49
|
return localStream;
|
|
38
50
|
}
|
|
39
51
|
|
|
40
|
-
interface ContactInfo {
|
|
41
|
-
id: string;
|
|
42
|
-
name: string;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export { ContactInfo };
|
|
46
52
|
export { setCurrentSession };
|
|
47
53
|
export { getCurrentSession };
|
|
48
54
|
export { setLocalStream };
|