@livedigital/client 2.18.2 → 2.19.1
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/dist/engine/system/index.d.ts +3 -3
- package/dist/index.es.js +1 -1
- package/dist/index.js +2 -2
- package/dist/types/common.d.ts +6 -0
- package/package.json +1 -1
- package/src/engine/index.ts +5 -0
- package/src/engine/system/index.ts +57 -32
- package/src/types/common.ts +7 -0
package/dist/types/common.d.ts
CHANGED
|
@@ -212,3 +212,9 @@ export declare type TransportConnectionTimeoutPayload = {
|
|
|
212
212
|
direction: 'receive' | 'send';
|
|
213
213
|
timeout: number;
|
|
214
214
|
};
|
|
215
|
+
export declare enum DeviceErrors {
|
|
216
|
+
NotFoundError = "NotFoundError",
|
|
217
|
+
NoDevices = "NoDevices",
|
|
218
|
+
DeviceIsBusy = "DeviceIsBusy",
|
|
219
|
+
NotAllowedError = "NotAllowedError"
|
|
220
|
+
}
|
package/package.json
CHANGED
package/src/engine/index.ts
CHANGED
|
@@ -208,6 +208,11 @@ class Engine {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
public setPeer(peerData: PeerResponse): Peer {
|
|
211
|
+
const existingPeer = this.peersRepository.get(peerData.id);
|
|
212
|
+
if (existingPeer) {
|
|
213
|
+
return existingPeer;
|
|
214
|
+
}
|
|
215
|
+
|
|
211
216
|
const peer = new Peer({
|
|
212
217
|
...peerData,
|
|
213
218
|
engine: this,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CreateSystemParams } from '../../types/engine';
|
|
2
2
|
import { CLIENT_EVENTS } from '../../constants/events';
|
|
3
3
|
import EnhancedEventEmitter from '../../EnhancedEventEmitter';
|
|
4
|
-
import { AvailableMediaDevices } from '../../types/common';
|
|
4
|
+
import { AvailableMediaDevices, DeviceErrors } from '../../types/common';
|
|
5
5
|
import Logger from '../Logger';
|
|
6
6
|
|
|
7
7
|
class System {
|
|
@@ -15,8 +15,6 @@ class System {
|
|
|
15
15
|
|
|
16
16
|
public availableAudioDevices: MediaDeviceInfo[] = [];
|
|
17
17
|
|
|
18
|
-
private isMediaDevicesAccessGranted = false;
|
|
19
|
-
|
|
20
18
|
public clientEventEmitter: EnhancedEventEmitter;
|
|
21
19
|
|
|
22
20
|
private readonly logger: Logger;
|
|
@@ -28,6 +26,9 @@ class System {
|
|
|
28
26
|
namespace: 'System',
|
|
29
27
|
logLevel,
|
|
30
28
|
});
|
|
29
|
+
|
|
30
|
+
this.deviceChangeHandler = this.deviceChangeHandler.bind(this);
|
|
31
|
+
|
|
31
32
|
this.listenDevices();
|
|
32
33
|
}
|
|
33
34
|
|
|
@@ -47,23 +48,28 @@ class System {
|
|
|
47
48
|
this.availableAudioDevices = availableAudioDevices;
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
async requestMediaDevicesAccess(): Promise<void> {
|
|
51
|
+
async requestMediaDevicesAccess(constraints: MediaStreamConstraints = { video: true, audio: true }): Promise<void> {
|
|
51
52
|
try {
|
|
52
|
-
const stream = await navigator.mediaDevices.getUserMedia(
|
|
53
|
-
video: true,
|
|
54
|
-
audio: true,
|
|
55
|
-
});
|
|
53
|
+
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
56
54
|
stream.getTracks().forEach((track) => track.stop());
|
|
57
|
-
this.isMediaDevicesAccessGranted = true;
|
|
58
55
|
} catch (error) {
|
|
59
|
-
this.logger.error('getUserMedia()', { error });
|
|
56
|
+
this.logger.error('getUserMedia()', { error, constraints });
|
|
57
|
+
|
|
58
|
+
if (error.name === 'NotAllowedError') {
|
|
59
|
+
throw new Error(DeviceErrors.NotAllowedError);
|
|
60
|
+
}
|
|
61
|
+
|
|
60
62
|
if (error.name === 'NotReadableError') {
|
|
61
|
-
throw new Error(
|
|
63
|
+
throw new Error(DeviceErrors.DeviceIsBusy);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (error.name === 'NotFoundError') {
|
|
67
|
+
throw new Error(DeviceErrors.NotFoundError);
|
|
62
68
|
}
|
|
63
69
|
}
|
|
64
70
|
}
|
|
65
71
|
|
|
66
|
-
async refreshAvailableMediaDevicesList(): Promise<
|
|
72
|
+
async refreshAvailableMediaDevicesList(): Promise<MediaDeviceInfo[]> {
|
|
67
73
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
68
74
|
const videoDevices = [] as MediaDeviceInfo[];
|
|
69
75
|
const audioDevices = [] as MediaDeviceInfo[];
|
|
@@ -72,10 +78,6 @@ class System {
|
|
|
72
78
|
return;
|
|
73
79
|
}
|
|
74
80
|
|
|
75
|
-
if (device.deviceId === 'default') {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
81
|
if (device.kind === 'videoinput') {
|
|
80
82
|
videoDevices.push(device);
|
|
81
83
|
}
|
|
@@ -89,6 +91,8 @@ class System {
|
|
|
89
91
|
this.setAvailableAudioDevices(audioDevices);
|
|
90
92
|
|
|
91
93
|
this.logger.debug('Devices list updated');
|
|
94
|
+
|
|
95
|
+
return devices;
|
|
92
96
|
}
|
|
93
97
|
|
|
94
98
|
async detectDevices(): Promise<void> {
|
|
@@ -96,31 +100,52 @@ class System {
|
|
|
96
100
|
return;
|
|
97
101
|
}
|
|
98
102
|
|
|
99
|
-
|
|
103
|
+
try {
|
|
100
104
|
await this.requestMediaDevicesAccess();
|
|
105
|
+
} catch (errorVideoAndAudio) {
|
|
106
|
+
if (errorVideoAndAudio.message !== DeviceErrors.NotFoundError) {
|
|
107
|
+
throw errorVideoAndAudio;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
await this.requestMediaDevicesAccess({ audio: true });
|
|
112
|
+
} catch (errorAudioOnly) {
|
|
113
|
+
if (errorAudioOnly.message !== DeviceErrors.NotFoundError) {
|
|
114
|
+
throw errorAudioOnly;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
await this.requestMediaDevicesAccess({ video: true });
|
|
118
|
+
}
|
|
101
119
|
}
|
|
102
120
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
121
|
+
this.isDevicesDetected = true;
|
|
122
|
+
|
|
123
|
+
// at this moment or access to device granted or no devices exists
|
|
124
|
+
|
|
125
|
+
const rawDevices = await this.refreshAvailableMediaDevicesList();
|
|
126
|
+
const hasAudioInputDevices = rawDevices.some((x) => x.kind === 'audioinput');
|
|
127
|
+
const hasVideoInputDevices = rawDevices.some((x) => x.kind === 'videoinput');
|
|
128
|
+
|
|
129
|
+
if (!hasAudioInputDevices && !hasVideoInputDevices) {
|
|
130
|
+
throw new Error(DeviceErrors.NoDevices);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async deviceChangeHandler(): Promise<void> {
|
|
135
|
+
if (!this.isDevicesDetected) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
106
138
|
|
|
107
139
|
await this.refreshAvailableMediaDevicesList();
|
|
108
140
|
|
|
109
|
-
this.
|
|
141
|
+
this.clientEventEmitter.safeEmit(CLIENT_EVENTS.devicesListUpdated, {
|
|
142
|
+
audio: this.availableAudioDevices,
|
|
143
|
+
video: this.availableVideoDevices,
|
|
144
|
+
} as AvailableMediaDevices);
|
|
110
145
|
}
|
|
111
146
|
|
|
112
147
|
listenDevices(): void {
|
|
113
|
-
navigator.mediaDevices.
|
|
114
|
-
if (!this.isDevicesDetected) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
await this.refreshAvailableMediaDevicesList();
|
|
119
|
-
this.clientEventEmitter.safeEmit(CLIENT_EVENTS.devicesListUpdated, {
|
|
120
|
-
audio: this.availableAudioDevices,
|
|
121
|
-
video: this.availableVideoDevices,
|
|
122
|
-
} as AvailableMediaDevices);
|
|
123
|
-
};
|
|
148
|
+
navigator.mediaDevices.addEventListener('devicechange', this.deviceChangeHandler);
|
|
124
149
|
}
|
|
125
150
|
}
|
|
126
151
|
|
package/src/types/common.ts
CHANGED
|
@@ -245,3 +245,10 @@ export type TransportConnectionTimeoutPayload = {
|
|
|
245
245
|
direction: 'receive' | 'send',
|
|
246
246
|
timeout: number,
|
|
247
247
|
};
|
|
248
|
+
|
|
249
|
+
export enum DeviceErrors {
|
|
250
|
+
NotFoundError = 'NotFoundError',
|
|
251
|
+
NoDevices = 'NoDevices',
|
|
252
|
+
DeviceIsBusy = 'DeviceIsBusy',
|
|
253
|
+
NotAllowedError = 'NotAllowedError',
|
|
254
|
+
}
|