@fishjam-cloud/react-client 0.7.1 → 0.8.0
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/DeviceManager.d.ts +25 -15
- package/dist/DeviceManager.d.ts.map +1 -1
- package/dist/DeviceManager.js +125 -79
- package/dist/devices/MiddlewareManager.d.ts +9 -0
- package/dist/devices/MiddlewareManager.d.ts.map +1 -0
- package/dist/devices/MiddlewareManager.js +26 -0
- package/dist/fishjamProvider.d.ts +5 -2
- package/dist/fishjamProvider.d.ts.map +1 -1
- package/dist/fishjamProvider.js +12 -4
- package/dist/hooks/deviceManagers/useDeviceManager.d.ts.map +1 -1
- package/dist/hooks/deviceManagers/useDeviceManager.js +2 -2
- package/dist/hooks/devices/useCamera.d.ts +7 -0
- package/dist/hooks/devices/useCamera.d.ts.map +1 -0
- package/dist/hooks/devices/useCamera.js +35 -0
- package/dist/hooks/devices/useInitializeDevices.d.ts +8 -0
- package/dist/hooks/devices/useInitializeDevices.d.ts.map +1 -0
- package/dist/hooks/devices/useInitializeDevices.js +41 -0
- package/dist/hooks/devices/useMicrophone.d.ts +7 -0
- package/dist/hooks/devices/useMicrophone.d.ts.map +1 -0
- package/dist/hooks/devices/useMicrophone.js +37 -0
- package/dist/hooks/public.d.ts +3 -1
- package/dist/hooks/public.d.ts.map +1 -1
- package/dist/hooks/public.js +3 -1
- package/dist/hooks/useFishjamContext.d.ts +4 -3
- package/dist/hooks/useFishjamContext.d.ts.map +1 -1
- package/dist/hooks/useScreenShare.d.ts +10 -1
- package/dist/hooks/useScreenShare.d.ts.map +1 -1
- package/dist/hooks/useScreenShare.js +34 -33
- package/dist/hooks/useTrackManager.d.ts +4 -2
- package/dist/hooks/useTrackManager.d.ts.map +1 -1
- package/dist/hooks/useTrackManager.js +55 -71
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/mediaInitializer.d.ts.map +1 -1
- package/dist/mediaInitializer.js +30 -1
- package/dist/types/internal.d.ts +20 -31
- package/dist/types/internal.d.ts.map +1 -1
- package/dist/types/public.d.ts +16 -5
- package/dist/types/public.d.ts.map +1 -1
- package/dist/utils/bandwidth.d.ts +3 -0
- package/dist/utils/bandwidth.d.ts.map +1 -0
- package/dist/utils/bandwidth.js +4 -0
- package/dist/utils/localStorage.d.ts +3 -4
- package/dist/utils/localStorage.d.ts.map +1 -1
- package/dist/utils/localStorage.js +18 -4
- package/dist/utils/track.d.ts +8 -2
- package/dist/utils/track.d.ts.map +1 -1
- package/dist/utils/track.js +23 -0
- package/package.json +5 -5
- package/dist/hooks/deviceManagers/useAudioDeviceManager.d.ts +0 -6
- package/dist/hooks/deviceManagers/useAudioDeviceManager.d.ts.map +0 -1
- package/dist/hooks/deviceManagers/useAudioDeviceManager.js +0 -11
- package/dist/hooks/deviceManagers/useVideoDeviceManager.d.ts +0 -6
- package/dist/hooks/deviceManagers/useVideoDeviceManager.d.ts.map +0 -1
- package/dist/hooks/deviceManagers/useVideoDeviceManager.js +0 -11
- package/dist/hooks/useDevices.d.ts +0 -19
- package/dist/hooks/useDevices.d.ts.map +0 -1
- package/dist/hooks/useDevices.js +0 -98
- package/dist/hooks/useProcessedPreviewStream.d.ts +0 -3
- package/dist/hooks/useProcessedPreviewStream.d.ts.map +0 -1
- package/dist/hooks/useProcessedPreviewStream.js +0 -17
- package/dist/utils/media.d.ts +0 -13
- package/dist/utils/media.d.ts.map +0 -1
- package/dist/utils/media.js +0 -64
package/dist/DeviceManager.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DeviceError, DeviceManagerStatus, DeviceState, Media, MediaManager } from "./types/internal";
|
|
2
2
|
import type TypedEmitter from "typed-emitter";
|
|
3
|
-
import type { PersistLastDeviceHandlers } from "./types/public";
|
|
3
|
+
import type { PersistLastDeviceHandlers, TrackMiddleware } from "./types/public";
|
|
4
|
+
export type DeviceType = "audio" | "video";
|
|
4
5
|
export type DeviceManagerEvents = {
|
|
5
6
|
managerStarted: (event: DeviceState & {
|
|
6
7
|
constraints: MediaTrackConstraints | undefined;
|
|
@@ -19,10 +20,11 @@ export type DeviceManagerEvents = {
|
|
|
19
20
|
deviceStopped: (state: DeviceState) => void;
|
|
20
21
|
deviceEnabled: (state: DeviceState) => void;
|
|
21
22
|
deviceDisabled: (state: DeviceState) => void;
|
|
23
|
+
middlewareSet: (state: DeviceState) => void;
|
|
22
24
|
error: (event: any, state: DeviceState) => void;
|
|
23
25
|
};
|
|
24
26
|
export type DeviceManagerConfig = {
|
|
25
|
-
deviceType:
|
|
27
|
+
deviceType: DeviceType;
|
|
26
28
|
defaultConstraints: MediaTrackConstraints;
|
|
27
29
|
userConstraints?: boolean | MediaTrackConstraints;
|
|
28
30
|
storage?: boolean | PersistLastDeviceHandlers;
|
|
@@ -30,26 +32,34 @@ export type DeviceManagerConfig = {
|
|
|
30
32
|
declare const DeviceManager_base: new () => TypedEmitter<DeviceManagerEvents>;
|
|
31
33
|
export declare class DeviceManager extends DeviceManager_base implements MediaManager {
|
|
32
34
|
private readonly constraints;
|
|
33
|
-
private readonly storageConfig;
|
|
34
35
|
private status;
|
|
35
36
|
private readonly deviceType;
|
|
36
|
-
|
|
37
|
+
private readonly middlewareManager;
|
|
38
|
+
readonly getLastDevice: () => MediaDeviceInfo | null;
|
|
39
|
+
private readonly saveLastDevice;
|
|
40
|
+
private rawMedia;
|
|
41
|
+
private processedMediaTrack;
|
|
42
|
+
private media;
|
|
43
|
+
private mediaStatus;
|
|
44
|
+
private devices;
|
|
45
|
+
private devicesStatus;
|
|
46
|
+
private error;
|
|
37
47
|
constructor({ deviceType, storage, userConstraints, defaultConstraints }: DeviceManagerConfig);
|
|
38
|
-
|
|
48
|
+
getState(): DeviceState;
|
|
39
49
|
getStatus(): DeviceManagerStatus;
|
|
40
50
|
getConstraints(): MediaTrackConstraints | boolean;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
initialize: (stream: MediaStream | null, track: MediaStreamTrack | null, devices: MediaDeviceInfo[], requestedMedia: boolean, error?: DeviceError | null) =>
|
|
44
|
-
private setupOnEndedCallback;
|
|
45
|
-
private onTrackEnded;
|
|
46
|
-
getLastDevice(): MediaDeviceInfo | null;
|
|
47
|
-
private saveLastDevice;
|
|
51
|
+
getDeviceType: () => DeviceType;
|
|
52
|
+
getMedia: () => Media | null;
|
|
53
|
+
initialize: (stream: MediaStream | null, track: MediaStreamTrack | null, devices: MediaDeviceInfo[], requestedMedia: boolean, error?: DeviceError | null) => void;
|
|
48
54
|
start(deviceId?: string): Promise<void>;
|
|
49
|
-
|
|
55
|
+
setTrackMiddleware(middleware: TrackMiddleware | null): Promise<void>;
|
|
56
|
+
getMiddleware(): TrackMiddleware | null;
|
|
57
|
+
stop(): void;
|
|
50
58
|
disable(): void;
|
|
51
59
|
enable(): void;
|
|
52
|
-
|
|
60
|
+
private setEnable;
|
|
61
|
+
private updateMedia;
|
|
62
|
+
private setCurrentMedia;
|
|
53
63
|
}
|
|
54
64
|
export {};
|
|
55
65
|
//# sourceMappingURL=DeviceManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceManager.d.ts","sourceRoot":"","sources":["../src/DeviceManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"DeviceManager.d.ts","sourceRoot":"","sources":["../src/DeviceManager.ts"],"names":[],"mappings":"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"}
|
package/dist/DeviceManager.js
CHANGED
|
@@ -1,31 +1,43 @@
|
|
|
1
1
|
import { prepareMediaTrackConstraints } from "./constraints";
|
|
2
2
|
import EventEmitter from "events";
|
|
3
|
-
import {
|
|
3
|
+
import { MiddlewareManager } from "./devices/MiddlewareManager";
|
|
4
|
+
import { createStorageConfig } from "./utils/localStorage";
|
|
5
|
+
import { setupOnEndedCallback } from "./utils/track";
|
|
4
6
|
import { parseUserMediaError } from "./utils/errors";
|
|
7
|
+
const NOOP = () => { };
|
|
5
8
|
export class DeviceManager extends EventEmitter {
|
|
6
9
|
constraints;
|
|
7
|
-
storageConfig;
|
|
8
10
|
status = "uninitialized";
|
|
9
11
|
deviceType;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
middlewareManager = new MiddlewareManager();
|
|
13
|
+
getLastDevice = () => null;
|
|
14
|
+
saveLastDevice = NOOP;
|
|
15
|
+
rawMedia = null;
|
|
16
|
+
processedMediaTrack = null;
|
|
17
|
+
media = null;
|
|
18
|
+
mediaStatus = "Not requested";
|
|
19
|
+
devices = null;
|
|
20
|
+
devicesStatus = "Not requested";
|
|
21
|
+
error = null;
|
|
17
22
|
constructor({ deviceType, storage, userConstraints, defaultConstraints }) {
|
|
18
23
|
super();
|
|
19
|
-
|
|
24
|
+
const storageConfig = createStorageConfig(deviceType, storage);
|
|
25
|
+
if (storageConfig) {
|
|
26
|
+
this.getLastDevice = storageConfig.getLastDevice;
|
|
27
|
+
this.saveLastDevice = storageConfig.saveLastDevice;
|
|
28
|
+
}
|
|
20
29
|
this.deviceType = deviceType;
|
|
21
30
|
this.constraints = userConstraints ?? defaultConstraints;
|
|
22
31
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
getState() {
|
|
33
|
+
return {
|
|
34
|
+
mediaStatus: this.mediaStatus,
|
|
35
|
+
devices: this.devices,
|
|
36
|
+
devicesStatus: this.devicesStatus,
|
|
37
|
+
error: this.error,
|
|
38
|
+
media: this.media,
|
|
39
|
+
currentMiddleware: this.middlewareManager.getMiddleware(),
|
|
40
|
+
};
|
|
29
41
|
}
|
|
30
42
|
getStatus() {
|
|
31
43
|
return this.status;
|
|
@@ -33,60 +45,49 @@ export class DeviceManager extends EventEmitter {
|
|
|
33
45
|
getConstraints() {
|
|
34
46
|
return this.constraints;
|
|
35
47
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
return stream?.getVideoTracks() ?? [];
|
|
48
|
+
getDeviceType = () => {
|
|
49
|
+
return this.deviceType;
|
|
50
|
+
};
|
|
51
|
+
getMedia = () => {
|
|
52
|
+
return this.media;
|
|
43
53
|
};
|
|
44
54
|
initialize = (stream, track, devices, requestedMedia, error = null) => {
|
|
45
|
-
|
|
46
|
-
const
|
|
55
|
+
const deviceInfo = getDeviceInfo(track?.getSettings()?.deviceId || null, devices);
|
|
56
|
+
const [devicesStatus, newError] = prepareStatus(requestedMedia, track);
|
|
57
|
+
this.devices = devices;
|
|
58
|
+
this.devicesStatus = devicesStatus;
|
|
59
|
+
this.mediaStatus = devicesStatus;
|
|
60
|
+
this.error = newError ?? error;
|
|
61
|
+
this.updateMedia({
|
|
62
|
+
stream: track ? stream : null,
|
|
63
|
+
track,
|
|
64
|
+
deviceInfo,
|
|
65
|
+
enabled: Boolean(track?.enabled),
|
|
66
|
+
});
|
|
47
67
|
if (deviceInfo)
|
|
48
|
-
this.saveLastDevice(deviceInfo);
|
|
68
|
+
this.saveLastDevice?.(deviceInfo);
|
|
49
69
|
this.status = "initialized";
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return this.deviceState;
|
|
53
|
-
};
|
|
54
|
-
setupOnEndedCallback() {
|
|
55
|
-
if (this.deviceState?.media?.track) {
|
|
56
|
-
this.deviceState.media.track.addEventListener("ended", async (event) => await this.onTrackEnded(event.target.id));
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
onTrackEnded = async (trackId) => {
|
|
60
|
-
if (trackId === this?.deviceState.media?.track?.id) {
|
|
61
|
-
await this.stop();
|
|
70
|
+
if (track) {
|
|
71
|
+
setupOnEndedCallback(track, () => this?.rawMedia?.track?.id, async () => this.stop());
|
|
62
72
|
}
|
|
73
|
+
this.emit("managerInitialized", this.getState());
|
|
63
74
|
};
|
|
64
|
-
getLastDevice() {
|
|
65
|
-
return this.storageConfig?.getLastDevice?.() ?? null;
|
|
66
|
-
}
|
|
67
|
-
saveLastDevice(info) {
|
|
68
|
-
this.storageConfig?.saveLastDevice(info);
|
|
69
|
-
}
|
|
70
75
|
async start(deviceId) {
|
|
71
|
-
const newDeviceId = deviceId ?? this.getLastDevice()?.deviceId;
|
|
72
|
-
const currentDeviceId = this.
|
|
76
|
+
const newDeviceId = deviceId ?? this.getLastDevice?.()?.deviceId;
|
|
77
|
+
const currentDeviceId = this.rawMedia?.deviceInfo?.deviceId;
|
|
73
78
|
const shouldReplaceDevice = Boolean(currentDeviceId && currentDeviceId !== newDeviceId);
|
|
74
79
|
const isDeviceStopped = currentDeviceId === undefined;
|
|
75
80
|
const shouldProceed = isDeviceStopped || shouldReplaceDevice;
|
|
76
81
|
const exactConstraints = shouldProceed && prepareMediaTrackConstraints(newDeviceId, this.constraints);
|
|
77
82
|
if (!exactConstraints)
|
|
78
83
|
return;
|
|
79
|
-
this.
|
|
80
|
-
this.emit("devicesStarted", {
|
|
84
|
+
this.mediaStatus = "Requesting";
|
|
85
|
+
this.emit("devicesStarted", { restarting: shouldReplaceDevice, constraints: exactConstraints }, this.getState());
|
|
81
86
|
try {
|
|
82
87
|
const stream = await navigator.mediaDevices.getUserMedia({ [this.deviceType]: exactConstraints });
|
|
83
|
-
const
|
|
84
|
-
const tracks = this.deviceType === "audio" ? stream.getAudioTracks() : stream.getVideoTracks();
|
|
85
|
-
return tracks[0] ?? null;
|
|
86
|
-
};
|
|
87
|
-
const track = getTrack();
|
|
88
|
+
const track = getTrack(stream, this.deviceType);
|
|
88
89
|
const currentDeviceId = track?.getSettings()?.deviceId;
|
|
89
|
-
const deviceInfo = currentDeviceId ? getDeviceInfo(currentDeviceId, this.
|
|
90
|
+
const deviceInfo = currentDeviceId ? getDeviceInfo(currentDeviceId, this.devices ?? []) : null;
|
|
90
91
|
if (deviceInfo) {
|
|
91
92
|
this.saveLastDevice?.(deviceInfo);
|
|
92
93
|
}
|
|
@@ -103,17 +104,20 @@ export class DeviceManager extends EventEmitter {
|
|
|
103
104
|
// The ended event in Safari has already been emitted and will be handled in the future.
|
|
104
105
|
// Therefore, in the `onTrackEnded` method, events for already stopped tracks are filtered out to prevent the state from being damaged.
|
|
105
106
|
if (shouldReplaceDevice) {
|
|
106
|
-
this.
|
|
107
|
+
this.rawMedia?.track?.stop();
|
|
108
|
+
this.processedMediaTrack?.stop();
|
|
107
109
|
}
|
|
108
|
-
this.
|
|
110
|
+
this.updateMedia({
|
|
109
111
|
stream,
|
|
110
112
|
track,
|
|
111
113
|
deviceInfo,
|
|
112
|
-
enabled:
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
enabled: Boolean(track?.enabled),
|
|
115
|
+
});
|
|
116
|
+
if (track) {
|
|
117
|
+
setupOnEndedCallback(track, () => this?.rawMedia?.track?.id, async () => this.stop());
|
|
118
|
+
}
|
|
119
|
+
this.mediaStatus = "OK";
|
|
120
|
+
this.emit("devicesReady", { ...this.getState(), restarted: shouldReplaceDevice }, this.getState());
|
|
117
121
|
}
|
|
118
122
|
catch (err) {
|
|
119
123
|
const parsedError = parseUserMediaError(err);
|
|
@@ -122,33 +126,75 @@ export class DeviceManager extends EventEmitter {
|
|
|
122
126
|
constraints: exactConstraints,
|
|
123
127
|
};
|
|
124
128
|
if (exactConstraints) {
|
|
125
|
-
this.
|
|
129
|
+
this.error = parsedError;
|
|
126
130
|
}
|
|
127
|
-
this.emit("error", event, this.
|
|
131
|
+
this.emit("error", event, this.getState());
|
|
128
132
|
}
|
|
129
133
|
}
|
|
130
|
-
async
|
|
131
|
-
this.
|
|
132
|
-
this.
|
|
133
|
-
this.
|
|
134
|
+
async setTrackMiddleware(middleware) {
|
|
135
|
+
const rawTrack = this.rawMedia?.track ?? null;
|
|
136
|
+
const processedMedia = this.middlewareManager.applyMiddleware(rawTrack, middleware);
|
|
137
|
+
this.setCurrentMedia(this.rawMedia, processedMedia);
|
|
138
|
+
this.emit("middlewareSet", this.getState());
|
|
139
|
+
}
|
|
140
|
+
getMiddleware() {
|
|
141
|
+
return this.middlewareManager.getMiddleware();
|
|
142
|
+
}
|
|
143
|
+
stop() {
|
|
144
|
+
this.middlewareManager.clearMiddleware();
|
|
145
|
+
this.processedMediaTrack?.stop();
|
|
146
|
+
this.rawMedia?.track?.stop();
|
|
147
|
+
this.updateMedia(null);
|
|
148
|
+
this.emit("deviceStopped", this.getState());
|
|
134
149
|
}
|
|
135
150
|
disable() {
|
|
136
|
-
|
|
137
|
-
|
|
151
|
+
this.setEnable(this.rawMedia?.track ?? null, false);
|
|
152
|
+
this.setEnable(this.processedMediaTrack, false);
|
|
153
|
+
if (this.media) {
|
|
154
|
+
this.media.enabled = false;
|
|
138
155
|
}
|
|
139
|
-
this.
|
|
140
|
-
this.deviceState.media.enabled = false;
|
|
141
|
-
this.emit("deviceDisabled", this.deviceState);
|
|
156
|
+
this.emit("deviceDisabled", this.getState());
|
|
142
157
|
}
|
|
143
158
|
enable() {
|
|
144
|
-
|
|
145
|
-
|
|
159
|
+
this.setEnable(this.rawMedia?.track ?? null, true);
|
|
160
|
+
this.setEnable(this.processedMediaTrack, true);
|
|
161
|
+
if (this.media) {
|
|
162
|
+
this.media.enabled = true;
|
|
146
163
|
}
|
|
147
|
-
this.
|
|
148
|
-
this.deviceState.media.enabled = true;
|
|
149
|
-
this.emit("deviceEnabled", this.deviceState);
|
|
164
|
+
this.emit("deviceEnabled", this.getState());
|
|
150
165
|
}
|
|
151
|
-
|
|
152
|
-
|
|
166
|
+
setEnable = (track, value) => {
|
|
167
|
+
if (!track)
|
|
168
|
+
return;
|
|
169
|
+
track.enabled = value;
|
|
153
170
|
};
|
|
171
|
+
updateMedia(media) {
|
|
172
|
+
this.rawMedia = !media ? null : { ...media };
|
|
173
|
+
const processedMedia = this.middlewareManager.applyMiddleware(media?.track ?? null);
|
|
174
|
+
this.setCurrentMedia(this.rawMedia, processedMedia);
|
|
175
|
+
}
|
|
176
|
+
setCurrentMedia(media, processedTrack) {
|
|
177
|
+
this.processedMediaTrack = processedTrack;
|
|
178
|
+
const streamTrack = processedTrack ? { track: processedTrack, stream: new MediaStream([processedTrack]) } : media;
|
|
179
|
+
this.media = streamTrack
|
|
180
|
+
? {
|
|
181
|
+
...streamTrack,
|
|
182
|
+
enabled: Boolean(streamTrack.track?.enabled),
|
|
183
|
+
deviceInfo: this.rawMedia?.deviceInfo ?? null,
|
|
184
|
+
}
|
|
185
|
+
: null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function getDeviceInfo(trackDeviceId, devices) {
|
|
189
|
+
return (trackDeviceId && devices.find(({ deviceId }) => trackDeviceId === deviceId)) || null;
|
|
190
|
+
}
|
|
191
|
+
function getTrack(stream, deviceType) {
|
|
192
|
+
return (deviceType === "audio" ? stream?.getAudioTracks()?.[0] : stream?.getVideoTracks()?.[0]) ?? null;
|
|
193
|
+
}
|
|
194
|
+
function prepareStatus(requested, track) {
|
|
195
|
+
if (!requested)
|
|
196
|
+
return ["Not requested", null];
|
|
197
|
+
if (track)
|
|
198
|
+
return ["OK", null];
|
|
199
|
+
return ["Error", null];
|
|
154
200
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TrackMiddleware } from "../types/public";
|
|
2
|
+
export declare class MiddlewareManager {
|
|
3
|
+
private middleware;
|
|
4
|
+
private clearMiddlewareFn;
|
|
5
|
+
getMiddleware(): TrackMiddleware | null;
|
|
6
|
+
clearMiddleware(): void;
|
|
7
|
+
applyMiddleware(rawTrack: MediaStreamTrack | null, middleware?: TrackMiddleware | null): MediaStreamTrack | null;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=MiddlewareManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MiddlewareManager.d.ts","sourceRoot":"","sources":["../../src/devices/MiddlewareManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAgC;IAClD,OAAO,CAAC,iBAAiB,CAA6B;IAE/C,aAAa,IAAI,eAAe,GAAG,IAAI;IAIvC,eAAe;IAKf,eAAe,CACpB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,EACjC,UAAU,GAAE,eAAe,GAAG,IAAsB,GACnD,gBAAgB,GAAG,IAAI;CAmB3B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { setupOnEndedCallback } from "../utils/track";
|
|
2
|
+
export class MiddlewareManager {
|
|
3
|
+
middleware = null;
|
|
4
|
+
clearMiddlewareFn = null;
|
|
5
|
+
getMiddleware() {
|
|
6
|
+
return this.middleware;
|
|
7
|
+
}
|
|
8
|
+
clearMiddleware() {
|
|
9
|
+
this.clearMiddlewareFn?.();
|
|
10
|
+
this.clearMiddlewareFn = null;
|
|
11
|
+
}
|
|
12
|
+
applyMiddleware(rawTrack, middleware = this.middleware) {
|
|
13
|
+
this.middleware = middleware;
|
|
14
|
+
this.clearMiddleware();
|
|
15
|
+
if (!rawTrack || !middleware)
|
|
16
|
+
return null;
|
|
17
|
+
const { onClear, track } = middleware(rawTrack);
|
|
18
|
+
if (onClear)
|
|
19
|
+
this.clearMiddlewareFn = onClear;
|
|
20
|
+
setupOnEndedCallback(track, () => track.id, async () => {
|
|
21
|
+
this.clearMiddleware();
|
|
22
|
+
track.stop();
|
|
23
|
+
});
|
|
24
|
+
return track;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { type PropsWithChildren } from "react";
|
|
2
2
|
import { type ReconnectConfig } from "@fishjam-cloud/ts-client";
|
|
3
|
-
import type { PersistLastDeviceHandlers } from "./types/public";
|
|
3
|
+
import type { BandwidthLimits, PersistLastDeviceHandlers, StartStreamingProps } from "./types/public";
|
|
4
4
|
interface FishjamProviderProps extends PropsWithChildren {
|
|
5
5
|
reconnect?: ReconnectConfig | boolean;
|
|
6
6
|
constraints?: Pick<MediaStreamConstraints, "audio" | "video">;
|
|
7
7
|
persistLastDevice?: boolean | PersistLastDeviceHandlers;
|
|
8
|
+
bandwidthLimits?: Partial<BandwidthLimits>;
|
|
9
|
+
autoStreamCamera?: StartStreamingProps | false;
|
|
10
|
+
autoStreamMicrophone?: StartStreamingProps | false;
|
|
8
11
|
}
|
|
9
12
|
/**
|
|
10
13
|
* @category Components
|
|
11
14
|
*/
|
|
12
|
-
export declare function FishjamProvider({ children, reconnect, constraints, persistLastDevice }: FishjamProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export declare function FishjamProvider({ children, reconnect, constraints, persistLastDevice, bandwidthLimits, autoStreamCamera, autoStreamMicrophone, }: FishjamProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
13
16
|
export {};
|
|
14
17
|
//# sourceMappingURL=fishjamProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fishjamProvider.d.ts","sourceRoot":"","sources":["../src/fishjamProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"fishjamProvider.d.ts","sourceRoot":"","sources":["../src/fishjamProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAGvD,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAO/E,OAAO,KAAK,EAAE,eAAe,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAItG,UAAU,oBAAqB,SAAQ,iBAAiB;IACtD,SAAS,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC;IACtC,WAAW,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC;IAC9D,iBAAiB,CAAC,EAAE,OAAO,GAAG,yBAAyB,CAAC;IACxD,eAAe,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3C,gBAAgB,CAAC,EAAE,mBAAmB,GAAG,KAAK,CAAC;IAC/C,oBAAoB,CAAC,EAAE,mBAAmB,GAAG,KAAK,CAAC;CACpD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,oBAAoB,GACrB,EAAE,oBAAoB,2CA8DtB"}
|
package/dist/fishjamProvider.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useRef
|
|
2
|
+
import { useRef } from "react";
|
|
3
3
|
import { useTrackManager } from "./hooks/useTrackManager";
|
|
4
4
|
import { FishjamClient } from "@fishjam-cloud/ts-client";
|
|
5
5
|
import { FishjamContext } from "./hooks/useFishjamContext";
|
|
@@ -7,10 +7,12 @@ import { DeviceManager } from "./DeviceManager";
|
|
|
7
7
|
import { usePeerStatus } from "./hooks/usePeerStatus";
|
|
8
8
|
import { useFishjamClientState } from "./hooks/useFishjamClientState";
|
|
9
9
|
import { AUDIO_TRACK_CONSTRAINTS, VIDEO_TRACK_CONSTRAINTS } from "./constraints";
|
|
10
|
+
import { useScreenShareManager } from "./hooks/useScreenShare";
|
|
11
|
+
import { mergeWithDefaultBandwitdthLimits } from "./utils/bandwidth";
|
|
10
12
|
/**
|
|
11
13
|
* @category Components
|
|
12
14
|
*/
|
|
13
|
-
export function FishjamProvider({ children, reconnect, constraints, persistLastDevice }) {
|
|
15
|
+
export function FishjamProvider({ children, reconnect, constraints, persistLastDevice, bandwidthLimits, autoStreamCamera, autoStreamMicrophone, }) {
|
|
14
16
|
const fishjamClientRef = useRef(new FishjamClient({ reconnect }));
|
|
15
17
|
const hasDevicesBeenInitializedRef = useRef(false);
|
|
16
18
|
const storage = persistLastDevice;
|
|
@@ -26,29 +28,35 @@ export function FishjamProvider({ children, reconnect, constraints, persistLastD
|
|
|
26
28
|
userConstraints: constraints?.audio,
|
|
27
29
|
storage,
|
|
28
30
|
}));
|
|
29
|
-
const screenShareState = useState({ stream: null, trackIds: null });
|
|
30
31
|
const { peerStatus, getCurrentPeerStatus } = usePeerStatus(fishjamClientRef.current);
|
|
32
|
+
const mergedBandwidthLimits = mergeWithDefaultBandwitdthLimits(bandwidthLimits);
|
|
31
33
|
const videoTrackManager = useTrackManager({
|
|
32
34
|
mediaManager: videoDeviceManagerRef.current,
|
|
33
35
|
tsClient: fishjamClientRef.current,
|
|
34
36
|
getCurrentPeerStatus,
|
|
37
|
+
bandwidthLimits: mergedBandwidthLimits,
|
|
38
|
+
autoStreamProps: autoStreamCamera,
|
|
35
39
|
});
|
|
36
40
|
const audioTrackManager = useTrackManager({
|
|
37
41
|
mediaManager: audioDeviceManagerRef.current,
|
|
38
42
|
tsClient: fishjamClientRef.current,
|
|
39
43
|
getCurrentPeerStatus,
|
|
44
|
+
bandwidthLimits: mergedBandwidthLimits,
|
|
45
|
+
autoStreamProps: autoStreamMicrophone,
|
|
40
46
|
});
|
|
47
|
+
const screenShareManager = useScreenShareManager({ fishjamClient: fishjamClientRef.current, getCurrentPeerStatus });
|
|
41
48
|
const clientState = useFishjamClientState(fishjamClientRef.current);
|
|
42
49
|
const context = {
|
|
43
50
|
fishjamClientRef,
|
|
44
51
|
peerStatus,
|
|
45
|
-
|
|
52
|
+
screenShareManager,
|
|
46
53
|
videoTrackManager,
|
|
47
54
|
audioTrackManager,
|
|
48
55
|
videoDeviceManagerRef,
|
|
49
56
|
audioDeviceManagerRef,
|
|
50
57
|
hasDevicesBeenInitializedRef,
|
|
51
58
|
clientState,
|
|
59
|
+
bandwidthLimits: mergedBandwidthLimits,
|
|
52
60
|
};
|
|
53
61
|
return _jsx(FishjamContext.Provider, { value: context, children: children });
|
|
54
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDeviceManager.d.ts","sourceRoot":"","sources":["../../../src/hooks/deviceManagers/useDeviceManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAuB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"useDeviceManager.d.ts","sourceRoot":"","sources":["../../../src/hooks/deviceManagers/useDeviceManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAuB,MAAM,qBAAqB,CAAC;AAe9E,eAAO,MAAM,gBAAgB,kBAAmB,aAAa,uBAmC5D,CAAC"}
|
|
@@ -9,6 +9,7 @@ const eventNames = [
|
|
|
9
9
|
"devicesReady",
|
|
10
10
|
"managerInitialized",
|
|
11
11
|
"error",
|
|
12
|
+
"middlewareSet",
|
|
12
13
|
];
|
|
13
14
|
export const useDeviceManager = (deviceManager) => {
|
|
14
15
|
const mutationRef = useRef(false);
|
|
@@ -26,9 +27,8 @@ export const useDeviceManager = (deviceManager) => {
|
|
|
26
27
|
const getSnapshot = useCallback(() => {
|
|
27
28
|
if (mutationRef.current || lastSnapshotRef.current === null) {
|
|
28
29
|
lastSnapshotRef.current = {
|
|
29
|
-
deviceState: deviceManager.
|
|
30
|
+
deviceState: deviceManager.getState(),
|
|
30
31
|
status: deviceManager.getStatus(),
|
|
31
|
-
tracks: deviceManager.getTracks(),
|
|
32
32
|
};
|
|
33
33
|
mutationRef.current = false;
|
|
34
34
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCamera.d.ts","sourceRoot":"","sources":["../../../src/hooks/devices/useCamera.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAIjD;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CA+BlC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useDeviceManager } from "../deviceManagers/useDeviceManager";
|
|
2
|
+
import { useFishjamContext } from "../useFishjamContext";
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @category Devices
|
|
6
|
+
*/
|
|
7
|
+
export function useCamera() {
|
|
8
|
+
const { videoTrackManager, videoDeviceManagerRef } = useFishjamContext();
|
|
9
|
+
const { deviceState, status } = useDeviceManager(videoDeviceManagerRef.current);
|
|
10
|
+
const { currentTrack, ...trackManager } = videoTrackManager;
|
|
11
|
+
const stream = deviceState.media?.stream ?? null;
|
|
12
|
+
const currentMiddleware = deviceState.currentMiddleware ?? null;
|
|
13
|
+
const isStreaming = Boolean(currentTrack?.stream);
|
|
14
|
+
const track = stream?.getAudioTracks()[0] ?? null;
|
|
15
|
+
const trackId = currentTrack?.trackId ?? null;
|
|
16
|
+
const devices = deviceState.devices ?? [];
|
|
17
|
+
const activeDevice = deviceState.media?.deviceInfo ?? null;
|
|
18
|
+
const isMuted = !deviceState.media?.enabled;
|
|
19
|
+
const deviceError = deviceState.error ?? null;
|
|
20
|
+
const isDeviceEnabled = Boolean(deviceState.media);
|
|
21
|
+
return {
|
|
22
|
+
...trackManager,
|
|
23
|
+
currentMiddleware,
|
|
24
|
+
status,
|
|
25
|
+
stream,
|
|
26
|
+
track,
|
|
27
|
+
devices,
|
|
28
|
+
activeDevice,
|
|
29
|
+
deviceError,
|
|
30
|
+
isMuted,
|
|
31
|
+
isStreaming,
|
|
32
|
+
trackId,
|
|
33
|
+
isDeviceEnabled,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInitializeDevices.d.ts","sourceRoot":"","sources":["../../../src/hooks/devices/useInitializeDevices.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;CAqDhC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { prepareConstraints } from "../../constraints";
|
|
3
|
+
import { getAvailableMedia, getCorrectedResult } from "../../mediaInitializer";
|
|
4
|
+
import { useFishjamContext } from "../useFishjamContext";
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @category Devices
|
|
8
|
+
*/
|
|
9
|
+
export const useInitializeDevices = () => {
|
|
10
|
+
const { videoDeviceManagerRef, audioDeviceManagerRef, hasDevicesBeenInitializedRef } = useFishjamContext();
|
|
11
|
+
const initializeDevices = useCallback(async () => {
|
|
12
|
+
if (hasDevicesBeenInitializedRef.current)
|
|
13
|
+
return;
|
|
14
|
+
hasDevicesBeenInitializedRef.current = true;
|
|
15
|
+
const videoManager = videoDeviceManagerRef.current;
|
|
16
|
+
const audioManager = audioDeviceManagerRef.current;
|
|
17
|
+
const constraints = {
|
|
18
|
+
video: videoManager.getConstraints(),
|
|
19
|
+
audio: audioManager.getConstraints(),
|
|
20
|
+
};
|
|
21
|
+
const previousDevices = {
|
|
22
|
+
video: videoManager.getLastDevice(),
|
|
23
|
+
audio: audioManager.getLastDevice(),
|
|
24
|
+
};
|
|
25
|
+
// Attempt to start the last selected device to avoid an unnecessary restart.
|
|
26
|
+
// Without this, the first device will start, and `getCorrectedResult` will attempt to fix it.
|
|
27
|
+
let [stream, deviceErrors] = await getAvailableMedia({
|
|
28
|
+
video: prepareConstraints(previousDevices.video?.deviceId, constraints.video),
|
|
29
|
+
audio: prepareConstraints(previousDevices.audio?.deviceId, constraints.audio),
|
|
30
|
+
});
|
|
31
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
32
|
+
const videoDevices = devices.filter(({ kind }) => kind === "videoinput");
|
|
33
|
+
const audioDevices = devices.filter(({ kind }) => kind === "audioinput");
|
|
34
|
+
if (stream) {
|
|
35
|
+
[stream, deviceErrors] = await getCorrectedResult(stream, deviceErrors, devices, constraints, previousDevices);
|
|
36
|
+
}
|
|
37
|
+
videoManager.initialize(stream, stream?.getVideoTracks()?.[0] ?? null, videoDevices, !!constraints.video, deviceErrors.video);
|
|
38
|
+
audioManager.initialize(stream, stream?.getAudioTracks()?.[0] ?? null, audioDevices, !!constraints.audio, deviceErrors.audio);
|
|
39
|
+
}, [videoDeviceManagerRef, audioDeviceManagerRef, hasDevicesBeenInitializedRef]);
|
|
40
|
+
return { initializeDevices };
|
|
41
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMicrophone.d.ts","sourceRoot":"","sources":["../../../src/hooks/devices/useMicrophone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD;;;GAGG;AACH,wBAAgB,aAAa,IAAI,WAAW,CAiC3C"}
|