livekit-client 0.17.5 → 0.17.6-rc1

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.
Files changed (153) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +26 -20
  3. package/dist/api/SignalClient.d.ts +1 -0
  4. package/dist/connect.d.ts +2 -0
  5. package/dist/index.d.ts +2 -2
  6. package/dist/livekit-client.esm.js +17344 -0
  7. package/dist/livekit-client.esm.js.map +1 -0
  8. package/dist/livekit-client.umd.js +17388 -0
  9. package/dist/livekit-client.umd.js.map +1 -0
  10. package/dist/logger.d.ts +22 -11
  11. package/dist/options.d.ts +4 -2
  12. package/dist/proto/google/protobuf/timestamp.d.ts +1 -1
  13. package/dist/proto/livekit_models.d.ts +4 -1
  14. package/dist/proto/livekit_rtc.d.ts +45 -2
  15. package/dist/room/DeviceManager.d.ts +1 -1
  16. package/dist/room/RTCEngine.d.ts +1 -1
  17. package/dist/room/Room.d.ts +2 -2
  18. package/dist/room/events.d.ts +1 -1
  19. package/dist/room/participant/LocalParticipant.d.ts +9 -5
  20. package/dist/room/participant/RemoteParticipant.d.ts +9 -0
  21. package/dist/room/track/RemoteAudioTrack.d.ts +11 -0
  22. package/dist/test/mocks.d.ts +11 -0
  23. package/package.json +40 -15
  24. package/.eslintrc.js +0 -17
  25. package/.gitmodules +0 -3
  26. package/dist/api/RequestQueue.js +0 -61
  27. package/dist/api/RequestQueue.js.map +0 -1
  28. package/dist/api/SignalClient.js +0 -428
  29. package/dist/api/SignalClient.js.map +0 -1
  30. package/dist/connect.js +0 -130
  31. package/dist/connect.js.map +0 -1
  32. package/dist/index.js +0 -71
  33. package/dist/index.js.map +0 -1
  34. package/dist/logger.js +0 -24
  35. package/dist/logger.js.map +0 -1
  36. package/dist/options.js +0 -3
  37. package/dist/options.js.map +0 -1
  38. package/dist/proto/google/protobuf/timestamp.js +0 -108
  39. package/dist/proto/google/protobuf/timestamp.js.map +0 -1
  40. package/dist/proto/livekit_models.js +0 -2262
  41. package/dist/proto/livekit_models.js.map +0 -1
  42. package/dist/proto/livekit_rtc.js +0 -2544
  43. package/dist/proto/livekit_rtc.js.map +0 -1
  44. package/dist/room/DeviceManager.js +0 -62
  45. package/dist/room/DeviceManager.js.map +0 -1
  46. package/dist/room/PCTransport.js +0 -91
  47. package/dist/room/PCTransport.js.map +0 -1
  48. package/dist/room/RTCEngine.js +0 -562
  49. package/dist/room/RTCEngine.js.map +0 -1
  50. package/dist/room/Room.js +0 -767
  51. package/dist/room/Room.js.map +0 -1
  52. package/dist/room/errors.js +0 -68
  53. package/dist/room/errors.js.map +0 -1
  54. package/dist/room/events.js +0 -385
  55. package/dist/room/events.js.map +0 -1
  56. package/dist/room/participant/LocalParticipant.js +0 -647
  57. package/dist/room/participant/LocalParticipant.js.map +0 -1
  58. package/dist/room/participant/Participant.js +0 -189
  59. package/dist/room/participant/Participant.js.map +0 -1
  60. package/dist/room/participant/ParticipantTrackPermission.js +0 -16
  61. package/dist/room/participant/ParticipantTrackPermission.js.map +0 -1
  62. package/dist/room/participant/RemoteParticipant.js +0 -194
  63. package/dist/room/participant/RemoteParticipant.js.map +0 -1
  64. package/dist/room/participant/publishUtils.js +0 -189
  65. package/dist/room/participant/publishUtils.js.map +0 -1
  66. package/dist/room/participant/publishUtils.test.d.ts +0 -1
  67. package/dist/room/participant/publishUtils.test.js +0 -118
  68. package/dist/room/participant/publishUtils.test.js.map +0 -1
  69. package/dist/room/stats.js +0 -26
  70. package/dist/room/stats.js.map +0 -1
  71. package/dist/room/track/LocalAudioTrack.js +0 -153
  72. package/dist/room/track/LocalAudioTrack.js.map +0 -1
  73. package/dist/room/track/LocalTrack.js +0 -158
  74. package/dist/room/track/LocalTrack.js.map +0 -1
  75. package/dist/room/track/LocalTrackPublication.js +0 -64
  76. package/dist/room/track/LocalTrackPublication.js.map +0 -1
  77. package/dist/room/track/LocalVideoTrack.js +0 -297
  78. package/dist/room/track/LocalVideoTrack.js.map +0 -1
  79. package/dist/room/track/LocalVideoTrack.test.d.ts +0 -1
  80. package/dist/room/track/LocalVideoTrack.test.js +0 -68
  81. package/dist/room/track/LocalVideoTrack.test.js.map +0 -1
  82. package/dist/room/track/RemoteAudioTrack.js +0 -64
  83. package/dist/room/track/RemoteAudioTrack.js.map +0 -1
  84. package/dist/room/track/RemoteTrack.js +0 -49
  85. package/dist/room/track/RemoteTrack.js.map +0 -1
  86. package/dist/room/track/RemoteTrackPublication.js +0 -178
  87. package/dist/room/track/RemoteTrackPublication.js.map +0 -1
  88. package/dist/room/track/RemoteVideoTrack.js +0 -201
  89. package/dist/room/track/RemoteVideoTrack.js.map +0 -1
  90. package/dist/room/track/Track.js +0 -283
  91. package/dist/room/track/Track.js.map +0 -1
  92. package/dist/room/track/TrackPublication.js +0 -92
  93. package/dist/room/track/TrackPublication.js.map +0 -1
  94. package/dist/room/track/create.js +0 -131
  95. package/dist/room/track/create.js.map +0 -1
  96. package/dist/room/track/defaults.js +0 -21
  97. package/dist/room/track/defaults.js.map +0 -1
  98. package/dist/room/track/options.js +0 -100
  99. package/dist/room/track/options.js.map +0 -1
  100. package/dist/room/track/types.js +0 -3
  101. package/dist/room/track/types.js.map +0 -1
  102. package/dist/room/track/utils.js +0 -113
  103. package/dist/room/track/utils.js.map +0 -1
  104. package/dist/room/track/utils.test.d.ts +0 -1
  105. package/dist/room/track/utils.test.js +0 -85
  106. package/dist/room/track/utils.test.js.map +0 -1
  107. package/dist/room/utils.js +0 -79
  108. package/dist/room/utils.js.map +0 -1
  109. package/dist/version.js +0 -6
  110. package/dist/version.js.map +0 -1
  111. package/jest.config.js +0 -6
  112. package/src/api/RequestQueue.ts +0 -53
  113. package/src/api/SignalClient.ts +0 -499
  114. package/src/connect.ts +0 -100
  115. package/src/index.ts +0 -47
  116. package/src/logger.ts +0 -22
  117. package/src/options.ts +0 -149
  118. package/src/proto/google/protobuf/timestamp.ts +0 -232
  119. package/src/proto/livekit_models.ts +0 -2676
  120. package/src/proto/livekit_rtc.ts +0 -3269
  121. package/src/room/DeviceManager.ts +0 -57
  122. package/src/room/PCTransport.ts +0 -86
  123. package/src/room/RTCEngine.ts +0 -652
  124. package/src/room/Room.ts +0 -951
  125. package/src/room/errors.ts +0 -65
  126. package/src/room/events.ts +0 -424
  127. package/src/room/participant/LocalParticipant.ts +0 -734
  128. package/src/room/participant/Participant.ts +0 -269
  129. package/src/room/participant/ParticipantTrackPermission.ts +0 -32
  130. package/src/room/participant/RemoteParticipant.ts +0 -243
  131. package/src/room/participant/publishUtils.test.ts +0 -145
  132. package/src/room/participant/publishUtils.ts +0 -225
  133. package/src/room/stats.ts +0 -130
  134. package/src/room/track/LocalAudioTrack.ts +0 -137
  135. package/src/room/track/LocalTrack.ts +0 -161
  136. package/src/room/track/LocalTrackPublication.ts +0 -66
  137. package/src/room/track/LocalVideoTrack.test.ts +0 -70
  138. package/src/room/track/LocalVideoTrack.ts +0 -293
  139. package/src/room/track/RemoteAudioTrack.ts +0 -58
  140. package/src/room/track/RemoteTrack.ts +0 -62
  141. package/src/room/track/RemoteTrackPublication.ts +0 -198
  142. package/src/room/track/RemoteVideoTrack.ts +0 -235
  143. package/src/room/track/Track.ts +0 -343
  144. package/src/room/track/TrackPublication.ts +0 -120
  145. package/src/room/track/create.ts +0 -121
  146. package/src/room/track/defaults.ts +0 -23
  147. package/src/room/track/options.ts +0 -281
  148. package/src/room/track/types.ts +0 -20
  149. package/src/room/track/utils.test.ts +0 -93
  150. package/src/room/track/utils.ts +0 -115
  151. package/src/room/utils.ts +0 -70
  152. package/src/version.ts +0 -2
  153. package/tsconfig.eslint.json +0 -11
package/dist/room/Room.js DELETED
@@ -1,767 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
- }) : (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- o[k2] = m[k];
8
- }));
9
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
- Object.defineProperty(o, "default", { enumerable: true, value: v });
11
- }) : function(o, v) {
12
- o["default"] = v;
13
- });
14
- var __importStar = (this && this.__importStar) || function (mod) {
15
- if (mod && mod.__esModule) return mod;
16
- var result = {};
17
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
- __setModuleDefault(result, mod);
19
- return result;
20
- };
21
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
22
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
23
- return new (P || (P = Promise))(function (resolve, reject) {
24
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
25
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
26
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
27
- step((generator = generator.apply(thisArg, _arguments || [])).next());
28
- });
29
- };
30
- var __importDefault = (this && this.__importDefault) || function (mod) {
31
- return (mod && mod.__esModule) ? mod : { "default": mod };
32
- };
33
- Object.defineProperty(exports, "__esModule", { value: true });
34
- exports.RoomState = void 0;
35
- const events_1 = require("events");
36
- const SignalClient_1 = require("../api/SignalClient");
37
- const logger_1 = __importDefault(require("../logger"));
38
- const livekit_models_1 = require("../proto/livekit_models");
39
- const livekit_rtc_1 = require("../proto/livekit_rtc");
40
- const DeviceManager_1 = __importDefault(require("./DeviceManager"));
41
- const errors_1 = require("./errors");
42
- const events_2 = require("./events");
43
- const LocalParticipant_1 = __importDefault(require("./participant/LocalParticipant"));
44
- const RemoteParticipant_1 = __importDefault(require("./participant/RemoteParticipant"));
45
- const RTCEngine_1 = __importStar(require("./RTCEngine"));
46
- const defaults_1 = require("./track/defaults");
47
- const RemoteTrackPublication_1 = __importDefault(require("./track/RemoteTrackPublication"));
48
- const Track_1 = require("./track/Track");
49
- const utils_1 = require("./track/utils");
50
- const utils_2 = require("./utils");
51
- var RoomState;
52
- (function (RoomState) {
53
- RoomState["Disconnected"] = "disconnected";
54
- RoomState["Connected"] = "connected";
55
- RoomState["Reconnecting"] = "reconnecting";
56
- })(RoomState = exports.RoomState || (exports.RoomState = {}));
57
- /**
58
- * In LiveKit, a room is the logical grouping for a list of participants.
59
- * Participants in a room can publish tracks, and subscribe to others' tracks.
60
- *
61
- * a Room fires [[RoomEvent | RoomEvents]].
62
- *
63
- * @noInheritDoc
64
- */
65
- class Room extends events_1.EventEmitter {
66
- /**
67
- * Creates a new Room, the primary construct for a LiveKit session.
68
- * @param options
69
- */
70
- constructor(options) {
71
- var _a, _b;
72
- super();
73
- this.state = RoomState.Disconnected;
74
- /**
75
- * list of participants that are actively speaking. when this changes
76
- * a [[RoomEvent.ActiveSpeakersChanged]] event is fired
77
- */
78
- this.activeSpeakers = [];
79
- // available after connected
80
- /** server assigned unique room id */
81
- this.sid = '';
82
- /** user assigned name, derived from JWT token */
83
- this.name = '';
84
- /** room metadata */
85
- this.metadata = undefined;
86
- this.audioEnabled = true;
87
- this.connect = (url, token, opts) => __awaiter(this, void 0, void 0, function* () {
88
- // guard against calling connect
89
- if (this.state !== RoomState.Disconnected) {
90
- logger_1.default.warn('already connected to room', this.name);
91
- return;
92
- }
93
- // recreate engine if previously disconnected
94
- this.createEngine();
95
- this.acquireAudioContext();
96
- if (opts === null || opts === void 0 ? void 0 : opts.rtcConfig) {
97
- this.engine.rtcConfig = opts.rtcConfig;
98
- }
99
- this.connOptions = opts;
100
- try {
101
- const joinResponse = yield this.engine.join(url, token, opts);
102
- logger_1.default.debug(`connected to Livekit Server version: ${joinResponse.serverVersion}, region: ${joinResponse.serverRegion}`);
103
- if (!joinResponse.serverVersion) {
104
- throw new errors_1.UnsupportedServer('unknown server version');
105
- }
106
- if (joinResponse.serverVersion === '0.15.1' && this.options.dynacast) {
107
- logger_1.default.debug('disabling dynacast due to server version');
108
- // dynacast has a bug in 0.15.1, so we cannot use it then
109
- this.options.dynacast = false;
110
- }
111
- this.state = RoomState.Connected;
112
- this.emit(events_2.RoomEvent.StateChanged, this.state);
113
- const pi = joinResponse.participant;
114
- this.localParticipant.sid = pi.sid;
115
- this.localParticipant.identity = pi.identity;
116
- this.localParticipant.updateInfo(pi);
117
- // forward metadata changed for the local participant
118
- this.localParticipant
119
- .on(events_2.ParticipantEvent.MetadataChanged, (metadata) => {
120
- this.emit(events_2.RoomEvent.MetadataChanged, metadata, this.localParticipant);
121
- })
122
- .on(events_2.ParticipantEvent.ParticipantMetadataChanged, (metadata) => {
123
- this.emit(events_2.RoomEvent.ParticipantMetadataChanged, metadata, this.localParticipant);
124
- })
125
- .on(events_2.ParticipantEvent.TrackMuted, (pub) => {
126
- this.emit(events_2.RoomEvent.TrackMuted, pub, this.localParticipant);
127
- })
128
- .on(events_2.ParticipantEvent.TrackUnmuted, (pub) => {
129
- this.emit(events_2.RoomEvent.TrackUnmuted, pub, this.localParticipant);
130
- })
131
- .on(events_2.ParticipantEvent.LocalTrackPublished, (pub) => {
132
- this.emit(events_2.RoomEvent.LocalTrackPublished, pub, this.localParticipant);
133
- })
134
- .on(events_2.ParticipantEvent.LocalTrackUnpublished, (pub) => {
135
- this.emit(events_2.RoomEvent.LocalTrackUnpublished, pub, this.localParticipant);
136
- })
137
- .on(events_2.ParticipantEvent.ConnectionQualityChanged, (quality) => {
138
- this.emit(events_2.RoomEvent.ConnectionQualityChanged, quality, this.localParticipant);
139
- })
140
- .on(events_2.ParticipantEvent.MediaDevicesError, (e) => {
141
- this.emit(events_2.RoomEvent.MediaDevicesError, e);
142
- })
143
- .on(events_2.ParticipantEvent.ParticipantPermissionsChanged, (prevPermissions) => {
144
- this.emit(events_2.RoomEvent.ParticipantPermissionsChanged, prevPermissions, this.localParticipant);
145
- });
146
- // populate remote participants, these should not trigger new events
147
- joinResponse.otherParticipants.forEach((info) => {
148
- this.getOrCreateParticipant(info.sid, info);
149
- });
150
- this.name = joinResponse.room.name;
151
- this.sid = joinResponse.room.sid;
152
- this.metadata = joinResponse.room.metadata;
153
- }
154
- catch (err) {
155
- this.engine.close();
156
- throw err;
157
- }
158
- // don't return until ICE connected
159
- return new Promise((resolve, reject) => {
160
- const connectTimeout = setTimeout(() => {
161
- // timeout
162
- this.engine.close();
163
- reject(new errors_1.ConnectionError('could not connect after timeout'));
164
- }, RTCEngine_1.maxICEConnectTimeout);
165
- this.engine.once(events_2.EngineEvent.Connected, () => {
166
- clearTimeout(connectTimeout);
167
- // also hook unload event
168
- if (utils_2.isWeb()) {
169
- window.addEventListener('beforeunload', this.onBeforeUnload);
170
- navigator.mediaDevices.addEventListener('devicechange', this.handleDeviceChange);
171
- }
172
- resolve(this);
173
- });
174
- });
175
- });
176
- /**
177
- * disconnects the room, emits [[RoomEvent.Disconnected]]
178
- */
179
- this.disconnect = (stopTracks = true) => {
180
- // send leave
181
- if (this.engine) {
182
- this.engine.client.sendLeave();
183
- this.engine.close();
184
- }
185
- this.handleDisconnect(stopTracks);
186
- /* @ts-ignore */
187
- this.engine = undefined;
188
- };
189
- this.onBeforeUnload = () => {
190
- this.disconnect();
191
- };
192
- this.handleRestarting = () => {
193
- this.state = RoomState.Reconnecting;
194
- this.emit(events_2.RoomEvent.Reconnecting);
195
- this.emit(events_2.RoomEvent.StateChanged, this.state);
196
- // also unwind existing participants & existing subscriptions
197
- for (const p of this.participants.values()) {
198
- this.handleParticipantDisconnected(p.sid, p);
199
- }
200
- };
201
- this.handleRestarted = (joinResponse) => __awaiter(this, void 0, void 0, function* () {
202
- logger_1.default.debug('reconnected to server region', joinResponse.serverRegion);
203
- this.state = RoomState.Connected;
204
- this.emit(events_2.RoomEvent.Reconnected);
205
- this.emit(events_2.RoomEvent.StateChanged, this.state);
206
- // rehydrate participants
207
- if (joinResponse.participant) {
208
- // with a restart, the sid will have changed, we'll map our understanding to it
209
- this.localParticipant.sid = joinResponse.participant.sid;
210
- this.handleParticipantUpdates([joinResponse.participant]);
211
- }
212
- this.handleParticipantUpdates(joinResponse.otherParticipants);
213
- // unpublish & republish tracks
214
- const localPubs = [];
215
- this.localParticipant.tracks.forEach((pub) => {
216
- if (pub.track) {
217
- localPubs.push(pub);
218
- }
219
- });
220
- yield Promise.all(localPubs.map((pub) => __awaiter(this, void 0, void 0, function* () {
221
- const track = pub.track;
222
- this.localParticipant.unpublishTrack(track, false);
223
- this.localParticipant.publishTrack(track, pub.options);
224
- })));
225
- });
226
- this.handleParticipantUpdates = (participantInfos) => {
227
- // handle changes to participant state, and send events
228
- participantInfos.forEach((info) => {
229
- if (info.sid === this.localParticipant.sid
230
- || info.identity === this.localParticipant.identity) {
231
- this.localParticipant.updateInfo(info);
232
- return;
233
- }
234
- let remoteParticipant = this.participants.get(info.sid);
235
- const isNewParticipant = !remoteParticipant;
236
- // create participant if doesn't exist
237
- remoteParticipant = this.getOrCreateParticipant(info.sid, info);
238
- // when it's disconnected, send updates
239
- if (info.state === livekit_models_1.ParticipantInfo_State.DISCONNECTED) {
240
- this.handleParticipantDisconnected(info.sid, remoteParticipant);
241
- }
242
- else if (isNewParticipant) {
243
- // fire connected event
244
- this.emit(events_2.RoomEvent.ParticipantConnected, remoteParticipant);
245
- }
246
- else {
247
- // just update, no events
248
- remoteParticipant.updateInfo(info);
249
- }
250
- });
251
- };
252
- // updates are sent only when there's a change to speaker ordering
253
- this.handleActiveSpeakersUpdate = (speakers) => {
254
- const activeSpeakers = [];
255
- const seenSids = {};
256
- speakers.forEach((speaker) => {
257
- seenSids[speaker.sid] = true;
258
- if (speaker.sid === this.localParticipant.sid) {
259
- this.localParticipant.audioLevel = speaker.level;
260
- this.localParticipant.setIsSpeaking(true);
261
- activeSpeakers.push(this.localParticipant);
262
- }
263
- else {
264
- const p = this.participants.get(speaker.sid);
265
- if (p) {
266
- p.audioLevel = speaker.level;
267
- p.setIsSpeaking(true);
268
- activeSpeakers.push(p);
269
- }
270
- }
271
- });
272
- if (!seenSids[this.localParticipant.sid]) {
273
- this.localParticipant.audioLevel = 0;
274
- this.localParticipant.setIsSpeaking(false);
275
- }
276
- this.participants.forEach((p) => {
277
- if (!seenSids[p.sid]) {
278
- p.audioLevel = 0;
279
- p.setIsSpeaking(false);
280
- }
281
- });
282
- this.activeSpeakers = activeSpeakers;
283
- this.emit(events_2.RoomEvent.ActiveSpeakersChanged, activeSpeakers);
284
- };
285
- // process list of changed speakers
286
- this.handleSpeakersChanged = (speakerUpdates) => {
287
- const lastSpeakers = new Map();
288
- this.activeSpeakers.forEach((p) => {
289
- lastSpeakers.set(p.sid, p);
290
- });
291
- speakerUpdates.forEach((speaker) => {
292
- let p = this.participants.get(speaker.sid);
293
- if (speaker.sid === this.localParticipant.sid) {
294
- p = this.localParticipant;
295
- }
296
- if (!p) {
297
- return;
298
- }
299
- p.audioLevel = speaker.level;
300
- p.setIsSpeaking(speaker.active);
301
- if (speaker.active) {
302
- lastSpeakers.set(speaker.sid, p);
303
- }
304
- else {
305
- lastSpeakers.delete(speaker.sid);
306
- }
307
- });
308
- const activeSpeakers = Array.from(lastSpeakers.values());
309
- activeSpeakers.sort((a, b) => b.audioLevel - a.audioLevel);
310
- this.activeSpeakers = activeSpeakers;
311
- this.emit(events_2.RoomEvent.ActiveSpeakersChanged, activeSpeakers);
312
- };
313
- this.handleStreamStateUpdate = (streamStateUpdate) => {
314
- streamStateUpdate.streamStates.forEach((streamState) => {
315
- const participant = this.participants.get(streamState.participantSid);
316
- if (!participant) {
317
- return;
318
- }
319
- const pub = participant.getTrackPublication(streamState.trackSid);
320
- if (!pub || !pub.track) {
321
- return;
322
- }
323
- pub.track.streamState = Track_1.Track.streamStateFromProto(streamState.state);
324
- participant.emit(events_2.ParticipantEvent.TrackStreamStateChanged, pub, pub.track.streamState);
325
- this.emit(events_2.ParticipantEvent.TrackStreamStateChanged, pub, pub.track.streamState, participant);
326
- });
327
- };
328
- this.handleSubscriptionPermissionUpdate = (update) => {
329
- const participant = this.participants.get(update.participantSid);
330
- if (!participant) {
331
- return;
332
- }
333
- const pub = participant.getTrackPublication(update.trackSid);
334
- if (!pub) {
335
- return;
336
- }
337
- pub._allowed = update.allowed;
338
- participant.emit(events_2.ParticipantEvent.TrackSubscriptionPermissionChanged, pub, pub.subscriptionStatus);
339
- this.emit(events_2.ParticipantEvent.TrackSubscriptionPermissionChanged, pub, pub.subscriptionStatus, participant);
340
- };
341
- this.handleDataPacket = (userPacket, kind) => {
342
- // find the participant
343
- const participant = this.participants.get(userPacket.participantSid);
344
- this.emit(events_2.RoomEvent.DataReceived, userPacket.payload, participant, kind);
345
- // also emit on the participant
346
- participant === null || participant === void 0 ? void 0 : participant.emit(events_2.ParticipantEvent.DataReceived, userPacket.payload, kind);
347
- };
348
- this.handleAudioPlaybackStarted = () => {
349
- if (this.canPlaybackAudio) {
350
- return;
351
- }
352
- this.audioEnabled = true;
353
- this.emit(events_2.RoomEvent.AudioPlaybackStatusChanged, true);
354
- };
355
- this.handleAudioPlaybackFailed = (e) => {
356
- logger_1.default.warn('could not playback audio', e);
357
- if (!this.canPlaybackAudio) {
358
- return;
359
- }
360
- this.audioEnabled = false;
361
- this.emit(events_2.RoomEvent.AudioPlaybackStatusChanged, false);
362
- };
363
- this.handleDeviceChange = () => __awaiter(this, void 0, void 0, function* () {
364
- this.emit(events_2.RoomEvent.MediaDevicesChanged);
365
- });
366
- this.handleRoomUpdate = (r) => {
367
- this.metadata = r.metadata;
368
- this.emit(events_2.RoomEvent.RoomMetadataChanged, r.metadata);
369
- };
370
- this.handleConnectionQualityUpdate = (update) => {
371
- update.updates.forEach((info) => {
372
- if (info.participantSid === this.localParticipant.sid) {
373
- this.localParticipant.setConnectionQuality(info.quality);
374
- return;
375
- }
376
- const participant = this.participants.get(info.participantSid);
377
- if (participant) {
378
- participant.setConnectionQuality(info.quality);
379
- }
380
- });
381
- };
382
- this.participants = new Map();
383
- this.options = options || {};
384
- switch ((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.publishDefaults) === null || _b === void 0 ? void 0 : _b.videoCodec) {
385
- case 'av1':
386
- case 'vp9':
387
- this.options.publishDefaults.simulcast = undefined;
388
- break;
389
- default:
390
- }
391
- this.options.audioCaptureDefaults = Object.assign(Object.assign({}, defaults_1.audioDefaults), options === null || options === void 0 ? void 0 : options.audioCaptureDefaults);
392
- this.options.videoCaptureDefaults = Object.assign(Object.assign({}, defaults_1.videoDefaults), options === null || options === void 0 ? void 0 : options.videoCaptureDefaults);
393
- this.options.publishDefaults = Object.assign(Object.assign({}, defaults_1.publishDefaults), options === null || options === void 0 ? void 0 : options.publishDefaults);
394
- this.createEngine();
395
- this.localParticipant = new LocalParticipant_1.default('', '', this.engine, this.options);
396
- }
397
- createEngine() {
398
- if (this.engine) {
399
- return;
400
- }
401
- this.engine = new RTCEngine_1.default();
402
- this.engine.client.signalLatency = this.options.expSignalLatency;
403
- this.engine.client.onParticipantUpdate = this.handleParticipantUpdates;
404
- this.engine.client.onRoomUpdate = this.handleRoomUpdate;
405
- this.engine.client.onSpeakersChanged = this.handleSpeakersChanged;
406
- this.engine.client.onStreamStateUpdate = this.handleStreamStateUpdate;
407
- this.engine.client.onSubscriptionPermissionUpdate = this.handleSubscriptionPermissionUpdate;
408
- this.engine.client.onConnectionQuality = this.handleConnectionQualityUpdate;
409
- this.engine
410
- .on(events_2.EngineEvent.MediaTrackAdded, (mediaTrack, stream, receiver) => {
411
- this.onTrackAdded(mediaTrack, stream, receiver);
412
- })
413
- .on(events_2.EngineEvent.Disconnected, () => {
414
- this.handleDisconnect();
415
- })
416
- .on(events_2.EngineEvent.ActiveSpeakersUpdate, this.handleActiveSpeakersUpdate)
417
- .on(events_2.EngineEvent.DataPacketReceived, this.handleDataPacket)
418
- .on(events_2.EngineEvent.Resuming, () => {
419
- this.state = RoomState.Reconnecting;
420
- this.emit(events_2.RoomEvent.Reconnecting);
421
- this.emit(events_2.RoomEvent.StateChanged, this.state);
422
- })
423
- .on(events_2.EngineEvent.Resumed, () => {
424
- this.state = RoomState.Connected;
425
- this.emit(events_2.RoomEvent.Reconnected);
426
- this.emit(events_2.RoomEvent.StateChanged, this.state);
427
- this.updateSubscriptions();
428
- })
429
- .on(events_2.EngineEvent.SignalResumed, () => {
430
- if (this.state === RoomState.Reconnecting) {
431
- this.sendSyncState();
432
- }
433
- })
434
- .on(events_2.EngineEvent.Restarting, this.handleRestarting)
435
- .on(events_2.EngineEvent.Restarted, this.handleRestarted);
436
- }
437
- /**
438
- * getLocalDevices abstracts navigator.mediaDevices.enumerateDevices.
439
- * In particular, it handles Chrome's unique behavior of creating `default`
440
- * devices. When encountered, it'll be removed from the list of devices.
441
- * The actual default device will be placed at top.
442
- * @param kind
443
- * @returns a list of available local devices
444
- */
445
- static getLocalDevices(kind) {
446
- return DeviceManager_1.default.getInstance().getDevices(kind);
447
- }
448
- /**
449
- * retrieves a participant by identity
450
- * @param identity
451
- * @returns
452
- */
453
- getParticipantByIdentity(identity) {
454
- for (const [, p] of this.participants) {
455
- if (p.identity === identity) {
456
- return p;
457
- }
458
- }
459
- if (this.localParticipant.identity === identity) {
460
- return this.localParticipant;
461
- }
462
- }
463
- /**
464
- * @internal for testing
465
- */
466
- simulateScenario(scenario) {
467
- let req;
468
- switch (scenario) {
469
- case 'speaker':
470
- req = livekit_rtc_1.SimulateScenario.fromPartial({
471
- speakerUpdate: 3,
472
- });
473
- break;
474
- case 'node-failure':
475
- req = livekit_rtc_1.SimulateScenario.fromPartial({
476
- nodeFailure: true,
477
- });
478
- break;
479
- case 'server-leave':
480
- req = livekit_rtc_1.SimulateScenario.fromPartial({
481
- serverLeave: true,
482
- });
483
- break;
484
- case 'migration':
485
- req = livekit_rtc_1.SimulateScenario.fromPartial({
486
- migration: true,
487
- });
488
- break;
489
- default:
490
- }
491
- if (req) {
492
- this.engine.client.sendSimulateScenario(req);
493
- }
494
- }
495
- /**
496
- * Browsers have different policies regarding audio playback. Most requiring
497
- * some form of user interaction (click/tap/etc).
498
- * In those cases, audio will be silent until a click/tap triggering one of the following
499
- * - `startAudio`
500
- * - `getUserMedia`
501
- */
502
- startAudio() {
503
- return __awaiter(this, void 0, void 0, function* () {
504
- this.acquireAudioContext();
505
- const elements = [];
506
- this.participants.forEach((p) => {
507
- p.audioTracks.forEach((t) => {
508
- if (t.track) {
509
- t.track.attachedElements.forEach((e) => {
510
- elements.push(e);
511
- });
512
- }
513
- });
514
- });
515
- try {
516
- yield Promise.all(elements.map((e) => e.play()));
517
- this.handleAudioPlaybackStarted();
518
- }
519
- catch (err) {
520
- this.handleAudioPlaybackFailed(err);
521
- throw err;
522
- }
523
- });
524
- }
525
- /**
526
- * Returns true if audio playback is enabled
527
- */
528
- get canPlaybackAudio() {
529
- return this.audioEnabled;
530
- }
531
- /**
532
- * Switches all active device used in this room to the given device.
533
- *
534
- * Note: setting AudioOutput is not supported on some browsers. See [setSinkId](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId#browser_compatibility)
535
- *
536
- * @param kind use `videoinput` for camera track,
537
- * `audioinput` for microphone track,
538
- * `audiooutput` to set speaker for all incoming audio tracks
539
- * @param deviceId
540
- */
541
- switchActiveDevice(kind, deviceId) {
542
- return __awaiter(this, void 0, void 0, function* () {
543
- if (kind === 'audioinput') {
544
- const tracks = Array
545
- .from(this.localParticipant.audioTracks.values())
546
- .filter((track) => track.source === Track_1.Track.Source.Microphone);
547
- yield Promise.all(tracks.map((t) => { var _a; return (_a = t.audioTrack) === null || _a === void 0 ? void 0 : _a.setDeviceId(deviceId); }));
548
- this.options.audioCaptureDefaults.deviceId = deviceId;
549
- }
550
- else if (kind === 'videoinput') {
551
- const tracks = Array
552
- .from(this.localParticipant.videoTracks.values())
553
- .filter((track) => track.source === Track_1.Track.Source.Camera);
554
- yield Promise.all(tracks.map((t) => { var _a; return (_a = t.videoTrack) === null || _a === void 0 ? void 0 : _a.setDeviceId(deviceId); }));
555
- this.options.videoCaptureDefaults.deviceId = deviceId;
556
- }
557
- else if (kind === 'audiooutput') {
558
- const elements = [];
559
- this.participants.forEach((p) => {
560
- p.audioTracks.forEach((t) => {
561
- if (t.isSubscribed && t.track) {
562
- t.track.attachedElements.forEach((e) => {
563
- elements.push(e);
564
- });
565
- }
566
- });
567
- });
568
- yield Promise.all(elements.map((e) => __awaiter(this, void 0, void 0, function* () {
569
- if ('setSinkId' in e) {
570
- /* @ts-ignore */
571
- yield e.setSinkId(deviceId);
572
- }
573
- })));
574
- }
575
- });
576
- }
577
- onTrackAdded(mediaTrack, stream, receiver) {
578
- const parts = utils_2.unpackStreamId(stream.id);
579
- const participantId = parts[0];
580
- let trackId = parts[1];
581
- if (!trackId || trackId === '')
582
- trackId = mediaTrack.id;
583
- const participant = this.getOrCreateParticipant(participantId);
584
- let adaptiveStreamSettings;
585
- if (this.options.adaptiveStream) {
586
- if (typeof this.options.adaptiveStream === 'object') {
587
- adaptiveStreamSettings = this.options.adaptiveStream;
588
- }
589
- else {
590
- adaptiveStreamSettings = {};
591
- }
592
- }
593
- participant.addSubscribedMediaTrack(mediaTrack, trackId, stream, receiver, adaptiveStreamSettings);
594
- }
595
- handleDisconnect(shouldStopTracks = true) {
596
- if (this.state === RoomState.Disconnected) {
597
- return;
598
- }
599
- this.participants.forEach((p) => {
600
- p.tracks.forEach((pub) => {
601
- p.unpublishTrack(pub.trackSid);
602
- });
603
- });
604
- this.localParticipant.tracks.forEach((pub) => {
605
- var _a, _b;
606
- if (pub.track) {
607
- this.localParticipant.unpublishTrack(pub.track);
608
- }
609
- if (shouldStopTracks) {
610
- (_a = pub.track) === null || _a === void 0 ? void 0 : _a.detach();
611
- (_b = pub.track) === null || _b === void 0 ? void 0 : _b.stop();
612
- }
613
- });
614
- this.participants.clear();
615
- this.activeSpeakers = [];
616
- if (this.audioContext) {
617
- this.audioContext.close();
618
- this.audioContext = undefined;
619
- }
620
- if (utils_2.isWeb()) {
621
- window.removeEventListener('beforeunload', this.onBeforeUnload);
622
- navigator.mediaDevices.removeEventListener('devicechange', this.handleDeviceChange);
623
- }
624
- this.state = RoomState.Disconnected;
625
- this.emit(events_2.RoomEvent.Disconnected);
626
- this.emit(events_2.RoomEvent.StateChanged, this.state);
627
- }
628
- handleParticipantDisconnected(sid, participant) {
629
- // remove and send event
630
- this.participants.delete(sid);
631
- if (!participant) {
632
- return;
633
- }
634
- participant.tracks.forEach((publication) => {
635
- participant.unpublishTrack(publication.trackSid);
636
- });
637
- this.emit(events_2.RoomEvent.ParticipantDisconnected, participant);
638
- }
639
- acquireAudioContext() {
640
- if (this.audioContext) {
641
- this.audioContext.close();
642
- }
643
- // by using an AudioContext, it reduces lag on audio elements
644
- // https://stackoverflow.com/questions/9811429/html5-audio-tag-on-safari-has-a-delay/54119854#54119854
645
- const ctx = utils_1.getNewAudioContext();
646
- if (ctx) {
647
- this.audioContext = ctx;
648
- }
649
- }
650
- createParticipant(id, info) {
651
- let participant;
652
- if (info) {
653
- participant = RemoteParticipant_1.default.fromParticipantInfo(this.engine.client, info);
654
- }
655
- else {
656
- participant = new RemoteParticipant_1.default(this.engine.client, id, '');
657
- }
658
- return participant;
659
- }
660
- getOrCreateParticipant(id, info) {
661
- if (this.participants.has(id)) {
662
- return this.participants.get(id);
663
- }
664
- // it's possible for the RTC track to arrive before signaling data
665
- // when this happens, we'll create the participant and make the track work
666
- const participant = this.createParticipant(id, info);
667
- this.participants.set(id, participant);
668
- // also forward events
669
- // trackPublished is only fired for tracks added after both local participant
670
- // and remote participant joined the room
671
- participant
672
- .on(events_2.ParticipantEvent.TrackPublished, (trackPublication) => {
673
- this.emit(events_2.RoomEvent.TrackPublished, trackPublication, participant);
674
- })
675
- .on(events_2.ParticipantEvent.TrackSubscribed, (track, publication) => {
676
- // monitor playback status
677
- if (track.kind === Track_1.Track.Kind.Audio) {
678
- track.on(events_2.TrackEvent.AudioPlaybackStarted, this.handleAudioPlaybackStarted);
679
- track.on(events_2.TrackEvent.AudioPlaybackFailed, this.handleAudioPlaybackFailed);
680
- }
681
- this.emit(events_2.RoomEvent.TrackSubscribed, track, publication, participant);
682
- })
683
- .on(events_2.ParticipantEvent.TrackUnpublished, (publication) => {
684
- this.emit(events_2.RoomEvent.TrackUnpublished, publication, participant);
685
- })
686
- .on(events_2.ParticipantEvent.TrackUnsubscribed, (track, publication) => {
687
- this.emit(events_2.RoomEvent.TrackUnsubscribed, track, publication, participant);
688
- })
689
- .on(events_2.ParticipantEvent.TrackSubscriptionFailed, (sid) => {
690
- this.emit(events_2.RoomEvent.TrackSubscriptionFailed, sid, participant);
691
- })
692
- .on(events_2.ParticipantEvent.TrackMuted, (pub) => {
693
- this.emit(events_2.RoomEvent.TrackMuted, pub, participant);
694
- })
695
- .on(events_2.ParticipantEvent.TrackUnmuted, (pub) => {
696
- this.emit(events_2.RoomEvent.TrackUnmuted, pub, participant);
697
- })
698
- .on(events_2.ParticipantEvent.MetadataChanged, (metadata) => {
699
- this.emit(events_2.RoomEvent.MetadataChanged, metadata, participant);
700
- })
701
- .on(events_2.ParticipantEvent.ParticipantMetadataChanged, (metadata) => {
702
- this.emit(events_2.RoomEvent.ParticipantMetadataChanged, metadata, participant);
703
- })
704
- .on(events_2.ParticipantEvent.ConnectionQualityChanged, (quality) => {
705
- this.emit(events_2.RoomEvent.ConnectionQualityChanged, quality, participant);
706
- })
707
- .on(events_2.ParticipantEvent.ParticipantPermissionsChanged, (prevPermissions) => {
708
- this.emit(events_2.RoomEvent.ParticipantPermissionsChanged, prevPermissions, participant);
709
- });
710
- return participant;
711
- }
712
- sendSyncState() {
713
- var _a;
714
- if (this.engine.subscriber === undefined
715
- || this.engine.subscriber.pc.localDescription === null) {
716
- return;
717
- }
718
- const previousSdp = this.engine.subscriber.pc.localDescription;
719
- /* 1. autosubscribe on, so subscribed tracks = all tracks - unsub tracks,
720
- in this case, we send unsub tracks, so server add all tracks to this
721
- subscribe pc and unsub special tracks from it.
722
- 2. autosubscribe off, we send subscribed tracks.
723
- */
724
- const sendUnsub = ((_a = this.connOptions) === null || _a === void 0 ? void 0 : _a.autoSubscribe) || false;
725
- const trackSids = new Array();
726
- this.participants.forEach((participant) => {
727
- participant.tracks.forEach((track) => {
728
- if (track.isSubscribed !== sendUnsub) {
729
- trackSids.push(track.trackSid);
730
- }
731
- });
732
- });
733
- this.engine.client.sendSyncState({
734
- answer: SignalClient_1.toProtoSessionDescription({
735
- sdp: previousSdp.sdp,
736
- type: previousSdp.type,
737
- }),
738
- subscription: {
739
- trackSids,
740
- subscribe: !sendUnsub,
741
- participantTracks: [],
742
- },
743
- publishTracks: this.localParticipant.publishedTracksInfo(),
744
- dataChannels: this.localParticipant.dataChannelsInfo(),
745
- });
746
- }
747
- /**
748
- * After resuming, we'll need to notify the server of the current
749
- * subscription settings.
750
- */
751
- updateSubscriptions() {
752
- for (const p of this.participants.values()) {
753
- for (const pub of p.videoTracks.values()) {
754
- if (pub.isSubscribed && pub instanceof RemoteTrackPublication_1.default) {
755
- pub.emitTrackUpdate();
756
- }
757
- }
758
- }
759
- }
760
- // /** @internal */
761
- emit(event, ...args) {
762
- logger_1.default.debug('room event', event, ...args);
763
- return super.emit(event, ...args);
764
- }
765
- }
766
- exports.default = Room;
767
- //# sourceMappingURL=Room.js.map