@epicgames-ps/lib-pixelstreamingfrontend-ue5.5 0.0.5
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/.cspell.json +48 -0
- package/.eslintignore +8 -0
- package/.eslintrc.js +8 -0
- package/.prettierignore +0 -0
- package/.prettierrc.json +6 -0
- package/dist/lib-pixelstreamingfrontend.esm.js +1 -0
- package/dist/lib-pixelstreamingfrontend.js +1 -0
- package/jest.config.js +18 -0
- package/package.json +48 -0
- package/readme.md +15 -0
- package/src/AFK/AFKController.test.ts +162 -0
- package/src/AFK/AFKController.ts +158 -0
- package/src/Config/Config.test.ts +222 -0
- package/src/Config/Config.ts +970 -0
- package/src/Config/SettingBase.ts +65 -0
- package/src/Config/SettingFlag.ts +99 -0
- package/src/Config/SettingNumber.ts +111 -0
- package/src/Config/SettingOption.ts +124 -0
- package/src/Config/SettingText.ts +82 -0
- package/src/DataChannel/DataChannelController.ts +138 -0
- package/src/DataChannel/DataChannelLatencyTestController.ts +129 -0
- package/src/DataChannel/DataChannelLatencyTestResults.ts +67 -0
- package/src/DataChannel/DataChannelSender.ts +59 -0
- package/src/DataChannel/InitialSettings.ts +61 -0
- package/src/DataChannel/LatencyTestResults.ts +76 -0
- package/src/FreezeFrame/FreezeFrame.ts +114 -0
- package/src/FreezeFrame/FreezeFrameController.ts +114 -0
- package/src/Inputs/FakeTouchController.ts +199 -0
- package/src/Inputs/GamepadController.ts +314 -0
- package/src/Inputs/GamepadTypes.ts +10 -0
- package/src/Inputs/HoveringMouseEvents.ts +192 -0
- package/src/Inputs/IMouseEvents.ts +64 -0
- package/src/Inputs/ITouchController.ts +29 -0
- package/src/Inputs/InputClassesFactory.ts +140 -0
- package/src/Inputs/KeyboardController.ts +354 -0
- package/src/Inputs/LockedMouseEvents.ts +287 -0
- package/src/Inputs/MouseButtons.ts +25 -0
- package/src/Inputs/MouseController.ts +362 -0
- package/src/Inputs/SpecialKeyCodes.ts +16 -0
- package/src/Inputs/TouchController.ts +208 -0
- package/src/Inputs/XRGamepadController.ts +126 -0
- package/src/PeerConnectionController/AggregatedStats.ts +311 -0
- package/src/PeerConnectionController/CandidatePairStats.ts +17 -0
- package/src/PeerConnectionController/CandidateStat.ts +13 -0
- package/src/PeerConnectionController/CodecStats.ts +19 -0
- package/src/PeerConnectionController/DataChannelStats.ts +17 -0
- package/src/PeerConnectionController/InboundRTPStats.ts +154 -0
- package/src/PeerConnectionController/InboundTrackStats.ts +34 -0
- package/src/PeerConnectionController/OutBoundRTPStats.ts +26 -0
- package/src/PeerConnectionController/PeerConnectionController.ts +563 -0
- package/src/PeerConnectionController/SessionStats.ts +10 -0
- package/src/PeerConnectionController/StreamStats.ts +11 -0
- package/src/PixelStreaming/PixelStreaming.test.ts +626 -0
- package/src/PixelStreaming/PixelStreaming.ts +851 -0
- package/src/UI/OnScreenKeyboard.ts +97 -0
- package/src/UeInstanceMessage/ResponseController.ts +47 -0
- package/src/UeInstanceMessage/SendMessageController.ts +154 -0
- package/src/UeInstanceMessage/StreamMessageController.ts +233 -0
- package/src/UeInstanceMessage/ToStreamerMessagesController.ts +62 -0
- package/src/Util/CoordinateConverter.ts +289 -0
- package/src/Util/EventEmitter.ts +611 -0
- package/src/Util/EventListenerTracker.ts +29 -0
- package/src/Util/FileUtil.ts +140 -0
- package/src/Util/RTCUtils.ts +41 -0
- package/src/Util/WebGLUtils.ts +49 -0
- package/src/Util/WebXRUtils.ts +25 -0
- package/src/VideoPlayer/StreamController.ts +89 -0
- package/src/VideoPlayer/VideoPlayer.ts +246 -0
- package/src/WebRtcPlayer/WebRtcPlayerController.ts +2158 -0
- package/src/WebXR/WebXRController.ts +319 -0
- package/src/__test__/mockMediaStream.ts +124 -0
- package/src/__test__/mockRTCPeerConnection.ts +347 -0
- package/src/__test__/mockRTCRtpReceiver.ts +22 -0
- package/src/__test__/mockWebSocket.ts +136 -0
- package/src/pixelstreamingfrontend.ts +46 -0
- package/tsconfig.jest.json +8 -0
- package/tsconfig.json +24 -0
- package/types/AFK/AFKController.d.ts +39 -0
- package/types/Config/Config.d.ts +218 -0
- package/types/Config/SettingBase.d.ts +30 -0
- package/types/Config/SettingFlag.d.ts +33 -0
- package/types/Config/SettingNumber.d.ts +45 -0
- package/types/Config/SettingOption.d.ts +43 -0
- package/types/Config/SettingText.d.ts +29 -0
- package/types/DataChannel/DataChannelController.d.ts +59 -0
- package/types/DataChannel/DataChannelLatencyTestController.d.ts +26 -0
- package/types/DataChannel/DataChannelLatencyTestResults.d.ts +46 -0
- package/types/DataChannel/DataChannelSender.d.ts +21 -0
- package/types/DataChannel/InitialSettings.d.ts +44 -0
- package/types/DataChannel/LatencyTestResults.d.ts +31 -0
- package/types/FreezeFrame/FreezeFrame.d.ts +36 -0
- package/types/FreezeFrame/FreezeFrameController.d.ts +37 -0
- package/types/Inputs/FakeTouchController.d.ts +61 -0
- package/types/Inputs/GamepadController.d.ts +85 -0
- package/types/Inputs/GamepadTypes.d.ts +8 -0
- package/types/Inputs/HoveringMouseEvents.d.ts +56 -0
- package/types/Inputs/IMouseEvents.d.ts +53 -0
- package/types/Inputs/ITouchController.d.ts +24 -0
- package/types/Inputs/InputClassesFactory.d.ts +54 -0
- package/types/Inputs/KeyboardController.d.ts +62 -0
- package/types/Inputs/LockedMouseEvents.d.ts +80 -0
- package/types/Inputs/MouseButtons.d.ts +22 -0
- package/types/Inputs/MouseController.d.ts +75 -0
- package/types/Inputs/SpecialKeyCodes.d.ts +14 -0
- package/types/Inputs/TouchController.d.ts +53 -0
- package/types/Inputs/XRGamepadController.d.ts +15 -0
- package/types/PeerConnectionController/AggregatedStats.d.ts +77 -0
- package/types/PeerConnectionController/CandidatePairStats.d.ts +15 -0
- package/types/PeerConnectionController/CandidateStat.d.ts +11 -0
- package/types/PeerConnectionController/CodecStats.d.ts +14 -0
- package/types/PeerConnectionController/DataChannelStats.d.ts +15 -0
- package/types/PeerConnectionController/InboundRTPStats.d.ts +141 -0
- package/types/PeerConnectionController/InboundTrackStats.d.ts +32 -0
- package/types/PeerConnectionController/OutBoundRTPStats.d.ts +23 -0
- package/types/PeerConnectionController/PeerConnectionController.d.ts +132 -0
- package/types/PeerConnectionController/SessionStats.d.ts +8 -0
- package/types/PeerConnectionController/StreamStats.d.ts +9 -0
- package/types/PixelStreaming/PixelStreaming.d.ts +259 -0
- package/types/UI/OnScreenKeyboard.d.ts +31 -0
- package/types/UeInstanceMessage/ResponseController.d.ts +19 -0
- package/types/UeInstanceMessage/SendMessageController.d.ts +18 -0
- package/types/UeInstanceMessage/StreamMessageController.d.ts +29 -0
- package/types/UeInstanceMessage/ToStreamerMessagesController.d.ts +32 -0
- package/types/Util/CoordinateConverter.d.ts +100 -0
- package/types/Util/EventEmitter.d.ts +422 -0
- package/types/Util/EventListenerTracker.d.ts +14 -0
- package/types/Util/FileUtil.d.ts +32 -0
- package/types/Util/RTCUtils.d.ts +8 -0
- package/types/Util/WebGLUtils.d.ts +4 -0
- package/types/Util/WebXRUtils.d.ts +9 -0
- package/types/VideoPlayer/StreamController.d.ts +24 -0
- package/types/VideoPlayer/VideoPlayer.d.ts +78 -0
- package/types/WebRtcPlayer/WebRtcPlayerController.d.ts +377 -0
- package/types/WebXR/WebXRController.d.ts +26 -0
- package/types/pixelstreamingfrontend.d.ts +22 -0
- package/webpack.common.js +35 -0
- package/webpack.dev.js +35 -0
- package/webpack.prod.js +36 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base class for a setting that has a text label and an arbitrary setting value it stores.
|
|
5
|
+
*/
|
|
6
|
+
export class SettingBase {
|
|
7
|
+
id: string;
|
|
8
|
+
description: string;
|
|
9
|
+
_label: string;
|
|
10
|
+
_value: unknown;
|
|
11
|
+
onChange: (changedValue: unknown, setting: SettingBase) => void;
|
|
12
|
+
onChangeEmit: (changedValue: unknown) => void;
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
id: string,
|
|
16
|
+
label: string,
|
|
17
|
+
description: string,
|
|
18
|
+
defaultSettingValue: unknown,
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
20
|
+
defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => { /* Do nothing, to be overridden. */ }
|
|
21
|
+
) {
|
|
22
|
+
this.onChange = defaultOnChangeListener;
|
|
23
|
+
|
|
24
|
+
this.onChangeEmit = () => {
|
|
25
|
+
/* Do nothing, to be overridden. */
|
|
26
|
+
};
|
|
27
|
+
this.id = id;
|
|
28
|
+
this.description = description;
|
|
29
|
+
this.label = label;
|
|
30
|
+
this.value = defaultSettingValue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Set the label text for the setting.
|
|
35
|
+
* @param label setting label.
|
|
36
|
+
*/
|
|
37
|
+
public set label(inLabel: string) {
|
|
38
|
+
this._label = inLabel;
|
|
39
|
+
this.onChangeEmit(this._value);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @returns The label text for the setting.
|
|
44
|
+
*/
|
|
45
|
+
public get label(): string {
|
|
46
|
+
return this._label;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @return The setting's value.
|
|
51
|
+
*/
|
|
52
|
+
public get value(): unknown {
|
|
53
|
+
return this._value;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Update the setting's stored value.
|
|
58
|
+
* @param inValue The new value for the setting.
|
|
59
|
+
*/
|
|
60
|
+
public set value(inValue: unknown) {
|
|
61
|
+
this._value = inValue;
|
|
62
|
+
this.onChange(this._value, this);
|
|
63
|
+
this.onChangeEmit(this._value);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
import type { FlagsIds } from './Config';
|
|
4
|
+
import { SettingBase } from './SettingBase';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A boolean flag setting object with a text label.
|
|
8
|
+
*/
|
|
9
|
+
export class SettingFlag<
|
|
10
|
+
CustomIds extends string = FlagsIds
|
|
11
|
+
> extends SettingBase {
|
|
12
|
+
id: FlagsIds | CustomIds;
|
|
13
|
+
onChangeEmit: (changedValue: boolean) => void;
|
|
14
|
+
useUrlParams: boolean;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
id: FlagsIds | CustomIds,
|
|
18
|
+
label: string,
|
|
19
|
+
description: string,
|
|
20
|
+
defaultFlagValue: boolean,
|
|
21
|
+
useUrlParams: boolean,
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
23
|
+
defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => { /* Do nothing, to be overridden. */ }
|
|
24
|
+
) {
|
|
25
|
+
super(id, label, description, defaultFlagValue, defaultOnChangeListener);
|
|
26
|
+
|
|
27
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
28
|
+
if (!useUrlParams || !urlParams.has(this.id)) {
|
|
29
|
+
this.flag = defaultFlagValue;
|
|
30
|
+
} else {
|
|
31
|
+
// parse flag from url parameters
|
|
32
|
+
const urlParamFlag = this.getUrlParamFlag();
|
|
33
|
+
this.flag = urlParamFlag;
|
|
34
|
+
}
|
|
35
|
+
this.useUrlParams = useUrlParams;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Parse the flag value from the url parameters.
|
|
40
|
+
* @returns True if the url parameters contains /?id, but False if /?id=false
|
|
41
|
+
*/
|
|
42
|
+
getUrlParamFlag(): boolean {
|
|
43
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
44
|
+
if (urlParams.has(this.id)) {
|
|
45
|
+
if (
|
|
46
|
+
urlParams.get(this.id) === 'false' ||
|
|
47
|
+
urlParams.get(this.id) === 'False'
|
|
48
|
+
) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Persist the setting value in URL.
|
|
58
|
+
*/
|
|
59
|
+
public updateURLParams() {
|
|
60
|
+
if (this.useUrlParams) {
|
|
61
|
+
// set url params
|
|
62
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
63
|
+
if (this.flag === true) {
|
|
64
|
+
urlParams.set(this.id, 'true');
|
|
65
|
+
} else {
|
|
66
|
+
urlParams.set(this.id, 'false');
|
|
67
|
+
}
|
|
68
|
+
window.history.replaceState(
|
|
69
|
+
{},
|
|
70
|
+
'',
|
|
71
|
+
urlParams.toString() !== ''
|
|
72
|
+
? `${location.pathname}?${urlParams}`
|
|
73
|
+
: `${location.pathname}`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Enables this flag.
|
|
80
|
+
*/
|
|
81
|
+
public enable(): void {
|
|
82
|
+
this.flag = true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @return The setting's value.
|
|
87
|
+
*/
|
|
88
|
+
public get flag(): boolean {
|
|
89
|
+
return !!this.value;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Update the setting's stored value.
|
|
94
|
+
* @param inValue The new value for the setting.
|
|
95
|
+
*/
|
|
96
|
+
public set flag(inValue: boolean) {
|
|
97
|
+
this.value = inValue;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
import type { NumericParametersIds } from './Config';
|
|
4
|
+
import { SettingBase } from './SettingBase';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A number setting object with a text label. Min and max limit the range of allowed values.
|
|
8
|
+
*/
|
|
9
|
+
export class SettingNumber<
|
|
10
|
+
CustomIds extends string = NumericParametersIds
|
|
11
|
+
> extends SettingBase {
|
|
12
|
+
_min: number;
|
|
13
|
+
_max: number;
|
|
14
|
+
|
|
15
|
+
id: NumericParametersIds | CustomIds;
|
|
16
|
+
onChangeEmit: (changedValue: number) => void;
|
|
17
|
+
useUrlParams: boolean;
|
|
18
|
+
|
|
19
|
+
constructor(
|
|
20
|
+
id: NumericParametersIds | CustomIds,
|
|
21
|
+
label: string,
|
|
22
|
+
description: string,
|
|
23
|
+
min: number,
|
|
24
|
+
max: number,
|
|
25
|
+
defaultNumber: number,
|
|
26
|
+
useUrlParams: boolean,
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
28
|
+
defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => { /* Do nothing, to be overridden. */ }
|
|
29
|
+
) {
|
|
30
|
+
super(id, label, description, defaultNumber, defaultOnChangeListener);
|
|
31
|
+
|
|
32
|
+
this._min = min;
|
|
33
|
+
this._max = max;
|
|
34
|
+
|
|
35
|
+
// attempt to read the number from the url params
|
|
36
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
37
|
+
if (!useUrlParams || !urlParams.has(this.id)) {
|
|
38
|
+
this.number = defaultNumber;
|
|
39
|
+
} else {
|
|
40
|
+
const parsedValue = Number.parseFloat(urlParams.get(this.id));
|
|
41
|
+
this.number = Number.isNaN(parsedValue)
|
|
42
|
+
? defaultNumber
|
|
43
|
+
: parsedValue;
|
|
44
|
+
}
|
|
45
|
+
this.useUrlParams = useUrlParams;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Persist the setting value in URL.
|
|
50
|
+
*/
|
|
51
|
+
public updateURLParams(): void {
|
|
52
|
+
if (this.useUrlParams) {
|
|
53
|
+
// set url params like ?id=number
|
|
54
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
55
|
+
urlParams.set(this.id, this.number.toString());
|
|
56
|
+
window.history.replaceState(
|
|
57
|
+
{},
|
|
58
|
+
'',
|
|
59
|
+
urlParams.toString() !== ''
|
|
60
|
+
? `${location.pathname}?${urlParams}`
|
|
61
|
+
: `${location.pathname}`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Set the number value (will be clamped within range).
|
|
68
|
+
*/
|
|
69
|
+
public set number(newNumber: number) {
|
|
70
|
+
this.value = this.clamp(newNumber);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @returns The number stored.
|
|
75
|
+
*/
|
|
76
|
+
public get number(): number {
|
|
77
|
+
return this.value as number;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Clamps a number between the min and max values (inclusive).
|
|
82
|
+
* @param inNumber The number to clamp.
|
|
83
|
+
* @returns The clamped number.
|
|
84
|
+
*/
|
|
85
|
+
public clamp(inNumber: number): number {
|
|
86
|
+
return Math.max(Math.min(this._max, inNumber), this._min);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Returns the minimum value
|
|
91
|
+
* @returns The minimum value
|
|
92
|
+
*/
|
|
93
|
+
public get min(): number {
|
|
94
|
+
return this._min;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Returns the maximum value
|
|
99
|
+
* @returns The maximum value
|
|
100
|
+
*/
|
|
101
|
+
public get max(): number {
|
|
102
|
+
return this._max;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Add a change listener to the number object.
|
|
107
|
+
*/
|
|
108
|
+
public addOnChangedListener(onChangedFunc: (newNumber: number) => void) {
|
|
109
|
+
this.onChange = onChangedFunc;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
import type { OptionParametersIds } from './Config';
|
|
4
|
+
import { SettingBase } from './SettingBase';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* An Option setting object with a text label. Allows you to specify an array of options and select one of them.
|
|
8
|
+
*/
|
|
9
|
+
export class SettingOption<
|
|
10
|
+
CustomIds extends string = OptionParametersIds
|
|
11
|
+
> extends SettingBase {
|
|
12
|
+
id: OptionParametersIds | CustomIds;
|
|
13
|
+
onChangeEmit: (changedValue: string) => void;
|
|
14
|
+
_options: Array<string>;
|
|
15
|
+
useUrlParams: boolean;
|
|
16
|
+
|
|
17
|
+
constructor(
|
|
18
|
+
id: OptionParametersIds | CustomIds,
|
|
19
|
+
label: string,
|
|
20
|
+
description: string,
|
|
21
|
+
defaultTextValue: string,
|
|
22
|
+
options: Array<string>,
|
|
23
|
+
useUrlParams: boolean,
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
25
|
+
defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => { /* Do nothing, to be overridden. */ }
|
|
26
|
+
) {
|
|
27
|
+
super(id, label, description, [defaultTextValue], defaultOnChangeListener);
|
|
28
|
+
|
|
29
|
+
this.options = options;
|
|
30
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
31
|
+
const stringToMatch: string =
|
|
32
|
+
useUrlParams && urlParams.has(this.id)
|
|
33
|
+
? this.getUrlParamText()
|
|
34
|
+
: defaultTextValue;
|
|
35
|
+
this.selected = stringToMatch;
|
|
36
|
+
this.useUrlParams = useUrlParams;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Parse the text value from the url parameters.
|
|
41
|
+
* @returns The text value parsed from the url if the url parameters contains /?id=value, but empty string if just /?id or no url param found.
|
|
42
|
+
*/
|
|
43
|
+
getUrlParamText(): string {
|
|
44
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
45
|
+
if (urlParams.has(this.id)) {
|
|
46
|
+
return urlParams.get(this.id) ?? '';
|
|
47
|
+
}
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Persist the setting value in URL.
|
|
53
|
+
*/
|
|
54
|
+
public updateURLParams() {
|
|
55
|
+
if (this.useUrlParams) {
|
|
56
|
+
// set url params
|
|
57
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
58
|
+
urlParams.set(this.id, this.selected);
|
|
59
|
+
window.history.replaceState(
|
|
60
|
+
{},
|
|
61
|
+
'',
|
|
62
|
+
urlParams.toString() !== ''
|
|
63
|
+
? `${location.pathname}?${urlParams}`
|
|
64
|
+
: `${location.pathname}`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Add a change listener to the select element.
|
|
71
|
+
*/
|
|
72
|
+
public addOnChangedListener(onChangedFunc: (newValue: string) => void) {
|
|
73
|
+
this.onChange = onChangedFunc;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @returns All available options as an array
|
|
78
|
+
*/
|
|
79
|
+
public get options(): Array<string> {
|
|
80
|
+
return this._options;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Set options
|
|
85
|
+
* @param values Array of options
|
|
86
|
+
*/
|
|
87
|
+
public set options(values: Array<string>) {
|
|
88
|
+
this._options = values;
|
|
89
|
+
this.onChangeEmit(this.selected);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @returns Selected option as a string
|
|
94
|
+
*/
|
|
95
|
+
public get selected(): string {
|
|
96
|
+
return this.value as string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Set selected option if it matches one of the available options
|
|
101
|
+
* @param value Selected option
|
|
102
|
+
*/
|
|
103
|
+
public set selected(value: string) {
|
|
104
|
+
// A user may not specify the full possible value so we instead use the closest match.
|
|
105
|
+
// eg ?xxx=H264 would select 'H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f'
|
|
106
|
+
let filteredList = this.options.filter(
|
|
107
|
+
(option: string) => option.indexOf(value) !== -1
|
|
108
|
+
);
|
|
109
|
+
if (filteredList.length) {
|
|
110
|
+
this.value = filteredList[0];
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// A user has specified a codec with a fmtp string but this codec + fmtp line isn't available.
|
|
115
|
+
// in that case, just use the codec
|
|
116
|
+
filteredList = this.options.filter(
|
|
117
|
+
(option: string) => option.indexOf(value.split(' ')[0]) !== -1
|
|
118
|
+
);
|
|
119
|
+
if (filteredList.length) {
|
|
120
|
+
this.value = filteredList[0];
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
import type { TextParametersIds } from './Config';
|
|
4
|
+
import { SettingBase } from './SettingBase';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A text setting object with a text label.
|
|
8
|
+
*/
|
|
9
|
+
export class SettingText<
|
|
10
|
+
CustomIds extends string = TextParametersIds
|
|
11
|
+
> extends SettingBase {
|
|
12
|
+
id: TextParametersIds | CustomIds;
|
|
13
|
+
onChangeEmit: (changedValue: string) => void;
|
|
14
|
+
useUrlParams: boolean;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
id: TextParametersIds | CustomIds,
|
|
18
|
+
label: string,
|
|
19
|
+
description: string,
|
|
20
|
+
defaultTextValue: string,
|
|
21
|
+
useUrlParams: boolean,
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
23
|
+
defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => { /* Do nothing, to be overridden. */ }
|
|
24
|
+
) {
|
|
25
|
+
super(id, label, description, defaultTextValue, defaultOnChangeListener);
|
|
26
|
+
|
|
27
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
28
|
+
if (!useUrlParams || !urlParams.has(this.id)) {
|
|
29
|
+
this.text = defaultTextValue;
|
|
30
|
+
} else {
|
|
31
|
+
// parse flag from url parameters
|
|
32
|
+
const urlParamFlag = this.getUrlParamText();
|
|
33
|
+
this.text = urlParamFlag;
|
|
34
|
+
}
|
|
35
|
+
this.useUrlParams = useUrlParams;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Parse the text value from the url parameters.
|
|
40
|
+
* @returns The text value parsed from the url if the url parameters contains /?id=value, but empty string if just /?id or no url param found.
|
|
41
|
+
*/
|
|
42
|
+
getUrlParamText(): string {
|
|
43
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
44
|
+
if (urlParams.has(this.id)) {
|
|
45
|
+
return urlParams.get(this.id) ?? '';
|
|
46
|
+
}
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Persist the setting value in URL.
|
|
52
|
+
*/
|
|
53
|
+
public updateURLParams() {
|
|
54
|
+
if (this.useUrlParams) {
|
|
55
|
+
// set url params
|
|
56
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
57
|
+
urlParams.set(this.id, this.text);
|
|
58
|
+
window.history.replaceState(
|
|
59
|
+
{},
|
|
60
|
+
'',
|
|
61
|
+
urlParams.toString() !== ''
|
|
62
|
+
? `${location.pathname}?${urlParams}`
|
|
63
|
+
: `${location.pathname}`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @return The setting's value.
|
|
70
|
+
*/
|
|
71
|
+
public get text(): string {
|
|
72
|
+
return this.value as string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Update the setting's stored value.
|
|
77
|
+
* @param inValue The new value for the setting.
|
|
78
|
+
*/
|
|
79
|
+
public set text(inValue: string) {
|
|
80
|
+
this.value = inValue;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Handles the Sending and Receiving of messages to the UE Instance via the Data Channel
|
|
7
|
+
*/
|
|
8
|
+
export class DataChannelController {
|
|
9
|
+
dataChannel: RTCDataChannel;
|
|
10
|
+
peerConnection: RTCPeerConnection;
|
|
11
|
+
datachannelOptions: RTCDataChannelInit;
|
|
12
|
+
label: string;
|
|
13
|
+
isReceivingFreezeFrame = false;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* return the current state of a datachannel controller instance
|
|
17
|
+
* @returns the current DataChannelController instance
|
|
18
|
+
*/
|
|
19
|
+
getDataChannelInstance(): DataChannelController {
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* To Create and Set up a Data Channel
|
|
25
|
+
* @param peerConnection - The RTC Peer Connection
|
|
26
|
+
* @param label - Label of the Data Channel
|
|
27
|
+
* @param datachannelOptions - Optional RTC DataChannel options
|
|
28
|
+
*/
|
|
29
|
+
createDataChannel(
|
|
30
|
+
peerConnection: RTCPeerConnection,
|
|
31
|
+
label: string,
|
|
32
|
+
datachannelOptions?: RTCDataChannelInit
|
|
33
|
+
) {
|
|
34
|
+
this.peerConnection = peerConnection;
|
|
35
|
+
this.label = label;
|
|
36
|
+
this.datachannelOptions = datachannelOptions;
|
|
37
|
+
if (datachannelOptions == null) {
|
|
38
|
+
this.datachannelOptions = {} as RTCDataChannelInit;
|
|
39
|
+
this.datachannelOptions.ordered = true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.dataChannel = this.peerConnection.createDataChannel(
|
|
43
|
+
this.label,
|
|
44
|
+
this.datachannelOptions
|
|
45
|
+
);
|
|
46
|
+
this.setupDataChannel();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setupDataChannel() {
|
|
50
|
+
//We Want an Array Buffer not a blob
|
|
51
|
+
this.dataChannel.binaryType = 'arraybuffer';
|
|
52
|
+
this.dataChannel.onopen = (ev: Event) => this.handleOnOpen(ev);
|
|
53
|
+
this.dataChannel.onclose = (ev: Event) => this.handleOnClose(ev);
|
|
54
|
+
this.dataChannel.onmessage = (ev: MessageEvent) =>
|
|
55
|
+
this.handleOnMessage(ev);
|
|
56
|
+
this.dataChannel.onerror = (ev: MessageEvent) => this.handleOnError(ev);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Handles when the Data Channel is opened
|
|
61
|
+
*/
|
|
62
|
+
handleOnOpen(ev: Event) {
|
|
63
|
+
Logger.Log(
|
|
64
|
+
Logger.GetStackTrace(),
|
|
65
|
+
`Data Channel (${this.label}) opened.`,
|
|
66
|
+
7
|
|
67
|
+
);
|
|
68
|
+
this.onOpen(this.dataChannel?.label, ev);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Handles when the Data Channel is closed
|
|
73
|
+
*/
|
|
74
|
+
handleOnClose(ev: Event) {
|
|
75
|
+
Logger.Log(
|
|
76
|
+
Logger.GetStackTrace(),
|
|
77
|
+
`Data Channel (${this.label}) closed.`,
|
|
78
|
+
7
|
|
79
|
+
);
|
|
80
|
+
this.onClose(this.dataChannel?.label, ev);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Handles when a message is received
|
|
85
|
+
* @param event - Message Event
|
|
86
|
+
*/
|
|
87
|
+
handleOnMessage(event: MessageEvent) {
|
|
88
|
+
// Higher log level to prevent log spam with messages received
|
|
89
|
+
Logger.Log(
|
|
90
|
+
Logger.GetStackTrace(),
|
|
91
|
+
`Data Channel (${this.label}) message: ${event}`,
|
|
92
|
+
8
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Handles when an error is thrown
|
|
98
|
+
* @param event - Error Event
|
|
99
|
+
*/
|
|
100
|
+
handleOnError(event: MessageEvent) {
|
|
101
|
+
Logger.Log(
|
|
102
|
+
Logger.GetStackTrace(),
|
|
103
|
+
`Data Channel (${this.label}) error: ${event}`,
|
|
104
|
+
7
|
|
105
|
+
);
|
|
106
|
+
this.onError(this.dataChannel?.label, event);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Override to register onOpen handler
|
|
111
|
+
* @param label Data channel label ("datachannel", "send-datachannel", "recv-datachannel")
|
|
112
|
+
* @param ev event
|
|
113
|
+
*/
|
|
114
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
115
|
+
onOpen(label: string, ev: Event) {
|
|
116
|
+
// empty default implementation
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Override to register onClose handler
|
|
121
|
+
* @param label Data channel label ("datachannel", "send-datachannel", "recv-datachannel")
|
|
122
|
+
* @param ev event
|
|
123
|
+
*/
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
125
|
+
onClose(label: string, ev: Event) {
|
|
126
|
+
// empty default implementation
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Override to register onError handler
|
|
131
|
+
* @param label Data channel label ("datachannel", "send-datachannel", "recv-datachannel")
|
|
132
|
+
* @param ev event
|
|
133
|
+
*/
|
|
134
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
135
|
+
onError(label: string, ev: Event) {
|
|
136
|
+
// empty default implementation
|
|
137
|
+
}
|
|
138
|
+
}
|