@epicgames-ps/lib-pixelstreamingfrontend-ue5.5 1.0.3 → 1.2.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/CHANGELOG.md +32 -0
- package/dist/cjs/Config/Config.js +8 -22
- package/dist/cjs/Config/Config.js.map +1 -1
- package/dist/cjs/Inputs/GamepadController.js.map +1 -1
- package/dist/cjs/Inputs/KeyboardController.js +0 -23
- package/dist/cjs/Inputs/KeyboardController.js.map +1 -1
- package/dist/cjs/Inputs/MouseController.js +9 -6
- package/dist/cjs/Inputs/MouseController.js.map +1 -1
- package/dist/cjs/Inputs/MouseControllerHovering.js.map +1 -1
- package/dist/cjs/Inputs/MouseControllerLocked.js +1 -0
- package/dist/cjs/Inputs/MouseControllerLocked.js.map +1 -1
- package/dist/cjs/PixelStreaming/PixelStreaming.js +12 -13
- package/dist/cjs/PixelStreaming/PixelStreaming.js.map +1 -1
- package/dist/cjs/UeInstanceMessage/StreamMessageController.js +4 -0
- package/dist/cjs/UeInstanceMessage/StreamMessageController.js.map +1 -1
- package/dist/cjs/Util/BrowserUtils.js +32 -0
- package/dist/cjs/Util/BrowserUtils.js.map +1 -0
- package/dist/cjs/Util/EventEmitter.js +11 -1
- package/dist/cjs/Util/EventEmitter.js.map +1 -1
- package/dist/cjs/Util/IURLSearchParams.js +1 -0
- package/dist/cjs/Util/IURLSearchParams.js.map +1 -1
- package/dist/cjs/Util/RTCUtils.js +1 -0
- package/dist/cjs/Util/RTCUtils.js.map +1 -1
- package/dist/cjs/VideoPlayer/VideoPlayer.js +12 -1
- package/dist/cjs/VideoPlayer/VideoPlayer.js.map +1 -1
- package/dist/cjs/WebRtcPlayer/WebRtcPlayerController.js +30 -6
- package/dist/cjs/WebRtcPlayer/WebRtcPlayerController.js.map +1 -1
- package/dist/esm/Config/Config.js +8 -22
- package/dist/esm/Config/Config.js.map +1 -1
- package/dist/esm/Inputs/GamepadController.js.map +1 -1
- package/dist/esm/Inputs/KeyboardController.js +0 -23
- package/dist/esm/Inputs/KeyboardController.js.map +1 -1
- package/dist/esm/Inputs/MouseController.js +9 -6
- package/dist/esm/Inputs/MouseController.js.map +1 -1
- package/dist/esm/Inputs/MouseControllerHovering.js.map +1 -1
- package/dist/esm/Inputs/MouseControllerLocked.js +1 -0
- package/dist/esm/Inputs/MouseControllerLocked.js.map +1 -1
- package/dist/esm/PixelStreaming/PixelStreaming.js +12 -13
- package/dist/esm/PixelStreaming/PixelStreaming.js.map +1 -1
- package/dist/esm/UeInstanceMessage/StreamMessageController.js +4 -0
- package/dist/esm/UeInstanceMessage/StreamMessageController.js.map +1 -1
- package/dist/esm/Util/BrowserUtils.js +28 -0
- package/dist/esm/Util/BrowserUtils.js.map +1 -0
- package/dist/esm/Util/EventEmitter.js +9 -0
- package/dist/esm/Util/EventEmitter.js.map +1 -1
- package/dist/esm/Util/IURLSearchParams.js +1 -0
- package/dist/esm/Util/IURLSearchParams.js.map +1 -1
- package/dist/esm/Util/RTCUtils.js +1 -0
- package/dist/esm/Util/RTCUtils.js.map +1 -1
- package/dist/esm/VideoPlayer/VideoPlayer.js +12 -1
- package/dist/esm/VideoPlayer/VideoPlayer.js.map +1 -1
- package/dist/esm/WebRtcPlayer/WebRtcPlayerController.js +31 -7
- package/dist/esm/WebRtcPlayer/WebRtcPlayerController.js.map +1 -1
- package/dist/types/Config/Config.d.ts +1 -0
- package/dist/types/Inputs/KeyboardController.d.ts +0 -2
- package/dist/types/PixelStreaming/PixelStreaming.d.ts +6 -6
- package/dist/types/Util/BrowserUtils.d.ts +3 -0
- package/dist/types/Util/EventEmitter.d.ts +14 -1
- package/dist/types/VideoPlayer/VideoPlayer.d.ts +2 -1
- package/dist/types/WebRtcPlayer/WebRtcPlayerController.d.ts +10 -5
- package/eslint.config.mjs +4 -4
- package/package.json +2 -2
- package/src/Config/Config.ts +18 -28
- package/src/Config/SettingBase.ts +1 -1
- package/src/Config/SettingFlag.ts +1 -1
- package/src/Config/SettingNumber.ts +1 -1
- package/src/Config/SettingOption.ts +2 -2
- package/src/Config/SettingText.ts +1 -1
- package/src/Inputs/GamepadController.ts +1 -2
- package/src/Inputs/IInputController.ts +1 -0
- package/src/Inputs/KeyboardController.ts +0 -31
- package/src/Inputs/MouseController.ts +9 -8
- package/src/Inputs/MouseControllerHovering.ts +1 -0
- package/src/Inputs/MouseControllerLocked.ts +1 -0
- package/src/PixelStreaming/PixelStreaming.ts +13 -19
- package/src/UeInstanceMessage/StreamMessageController.ts +4 -0
- package/src/Util/BrowserUtils.ts +36 -0
- package/src/Util/EventEmitter.ts +19 -0
- package/src/Util/IURLSearchParams.ts +1 -0
- package/src/Util/RTCUtils.ts +1 -0
- package/src/VideoPlayer/VideoPlayer.ts +14 -2
- package/src/WebRtcPlayer/WebRtcPlayerController.ts +34 -7
- package/tsconfig.cjs.json +3 -2
- package/tsconfig.esm.json +1 -1
- package/tsconfig.jest.json +1 -1
- package/{tsconfig.base.json → tsconfig.json} +2 -1
- package/dist/cjs/UI/OnScreenKeyboard.js +0 -86
- package/dist/cjs/UI/OnScreenKeyboard.js.map +0 -1
- package/dist/esm/UI/OnScreenKeyboard.js +0 -82
- package/dist/esm/UI/OnScreenKeyboard.js.map +0 -1
- package/dist/types/UI/OnScreenKeyboard.d.ts +0 -30
- package/src/UI/OnScreenKeyboard.ts +0 -102
package/src/Config/Config.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { SettingText } from './SettingText';
|
|
|
7
7
|
import { SettingOption } from './SettingOption';
|
|
8
8
|
import { PixelStreamingEventEmitter, SettingsChangedEvent } from '../Util/EventEmitter';
|
|
9
9
|
import { SettingBase } from './SettingBase';
|
|
10
|
+
import { BrowserUtils } from '../Util/BrowserUtils';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* A collection of flags that can be toggled and are core to all Pixel Streaming experiences.
|
|
@@ -25,6 +26,7 @@ export class Flags {
|
|
|
25
26
|
static StartVideoMuted = 'StartVideoMuted' as const;
|
|
26
27
|
static SuppressBrowserKeys = 'SuppressBrowserKeys' as const;
|
|
27
28
|
static UseMic = 'UseMic' as const;
|
|
29
|
+
static UseModalForTextInput = 'UseModalForTextInput' as const;
|
|
28
30
|
static UseCamera = 'UseCamera' as const;
|
|
29
31
|
static KeyboardInput = 'KeyboardInput' as const;
|
|
30
32
|
static MouseInput = 'MouseInput' as const;
|
|
@@ -214,33 +216,8 @@ export class Config {
|
|
|
214
216
|
)
|
|
215
217
|
);
|
|
216
218
|
|
|
217
|
-
const getBrowserSupportedVideoCodecs = function (): Array<string> {
|
|
218
|
-
const browserSupportedCodecs: Array<string> = [];
|
|
219
|
-
// Try get the info needed from the RTCRtpReceiver. This is only available on chrome
|
|
220
|
-
if (!RTCRtpReceiver.getCapabilities) {
|
|
221
|
-
Logger.Warning(
|
|
222
|
-
'RTCRtpReceiver.getCapabilities API is not available in your browser, defaulting to guess that we support H.264.'
|
|
223
|
-
);
|
|
224
|
-
browserSupportedCodecs.push(
|
|
225
|
-
'H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f'
|
|
226
|
-
);
|
|
227
|
-
return browserSupportedCodecs;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const matcher = /(VP\d|H26\d|AV1).*/;
|
|
231
|
-
const codecs = RTCRtpReceiver.getCapabilities('video').codecs;
|
|
232
|
-
codecs.forEach((codec) => {
|
|
233
|
-
const str = codec.mimeType.split('/')[1] + ' ' + (codec.sdpFmtpLine || '');
|
|
234
|
-
const match = matcher.exec(str);
|
|
235
|
-
if (match !== null) {
|
|
236
|
-
browserSupportedCodecs.push(str);
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
return browserSupportedCodecs;
|
|
240
|
-
};
|
|
241
|
-
|
|
242
219
|
const getDefaultVideoCodec = function (): string {
|
|
243
|
-
const videoCodecs =
|
|
220
|
+
const videoCodecs = BrowserUtils.getSupportedVideoCodecs();
|
|
244
221
|
// If only one option, then select that.
|
|
245
222
|
if (videoCodecs.length == 1) {
|
|
246
223
|
return videoCodecs[0];
|
|
@@ -259,7 +236,7 @@ export class Config {
|
|
|
259
236
|
};
|
|
260
237
|
|
|
261
238
|
const matchSpecifiedCodecToClosestSupported = function (specifiedCodec: string): string {
|
|
262
|
-
const browserSupportedCodecs: Array<string> =
|
|
239
|
+
const browserSupportedCodecs: Array<string> = BrowserUtils.getSupportedVideoCodecs();
|
|
263
240
|
|
|
264
241
|
// Codec supplied in url param is an exact match for the browser codec.
|
|
265
242
|
// (e.g. H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f)
|
|
@@ -290,7 +267,7 @@ export class Config {
|
|
|
290
267
|
settings && Object.prototype.hasOwnProperty.call(settings, OptionParameters.PreferredCodec)
|
|
291
268
|
? matchSpecifiedCodecToClosestSupported(settings[OptionParameters.PreferredCodec])
|
|
292
269
|
: getDefaultVideoCodec(),
|
|
293
|
-
|
|
270
|
+
BrowserUtils.getSupportedVideoCodecs(),
|
|
294
271
|
useUrlParams,
|
|
295
272
|
matchSpecifiedCodecToClosestSupported
|
|
296
273
|
)
|
|
@@ -353,6 +330,19 @@ export class Config {
|
|
|
353
330
|
)
|
|
354
331
|
);
|
|
355
332
|
|
|
333
|
+
this.flags.set(
|
|
334
|
+
Flags.UseModalForTextInput,
|
|
335
|
+
new SettingFlag(
|
|
336
|
+
Flags.UseModalForTextInput,
|
|
337
|
+
'Use modal for text input',
|
|
338
|
+
'When entering input into a streamed UE text widget, use an input modal.',
|
|
339
|
+
settings && Object.prototype.hasOwnProperty.call(settings, Flags.UseModalForTextInput)
|
|
340
|
+
? settings[Flags.UseModalForTextInput]
|
|
341
|
+
: true,
|
|
342
|
+
useUrlParams
|
|
343
|
+
)
|
|
344
|
+
);
|
|
345
|
+
|
|
356
346
|
this.flags.set(
|
|
357
347
|
Flags.UseCamera,
|
|
358
348
|
new SettingFlag(
|
|
@@ -16,7 +16,7 @@ export class SettingFlag<CustomIds extends string = FlagsIds> extends SettingBas
|
|
|
16
16
|
description: string,
|
|
17
17
|
defaultFlagValue: boolean,
|
|
18
18
|
useUrlParams: boolean,
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => {
|
|
21
21
|
/* Do nothing, to be overridden. */
|
|
22
22
|
}
|
|
@@ -21,7 +21,7 @@ export class SettingNumber<CustomIds extends string = NumericParametersIds> exte
|
|
|
21
21
|
max: number | null,
|
|
22
22
|
defaultNumber: number,
|
|
23
23
|
useUrlParams: boolean,
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => {
|
|
26
26
|
/* Do nothing, to be overridden. */
|
|
27
27
|
}
|
|
@@ -22,12 +22,12 @@ export class SettingOption<CustomIds extends string = OptionParametersIds> exten
|
|
|
22
22
|
defaultTextValue: string,
|
|
23
23
|
options: Array<string>,
|
|
24
24
|
useUrlParams: boolean,
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
defaultUrlParamResolver: (urlParamValue: string) => string = function (value: string) {
|
|
27
27
|
/* Return the string as-is by default */
|
|
28
28
|
return value;
|
|
29
29
|
},
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => {
|
|
32
32
|
/* Do nothing, to be overridden. */
|
|
33
33
|
}
|
|
@@ -17,7 +17,7 @@ export class SettingText<CustomIds extends string = TextParametersIds> extends S
|
|
|
17
17
|
description: string,
|
|
18
18
|
defaultTextValue: string,
|
|
19
19
|
useUrlParams: boolean,
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => {
|
|
22
22
|
/* Do nothing, to be overridden. */
|
|
23
23
|
}
|
|
@@ -21,7 +21,7 @@ declare global {
|
|
|
21
21
|
/**
|
|
22
22
|
* Gamepad layout codes enum
|
|
23
23
|
*/
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
export enum GamepadLayout {
|
|
26
26
|
RightClusterBottomButton = 0,
|
|
27
27
|
RightClusterRightButton = 1,
|
|
@@ -46,7 +46,6 @@ export enum GamepadLayout {
|
|
|
46
46
|
RightStickHorizontal = 2,
|
|
47
47
|
RightStickVertical = 3
|
|
48
48
|
}
|
|
49
|
-
|
|
50
49
|
|
|
51
50
|
/**
|
|
52
51
|
* Handles gamepad events from the document to send to the streamer.
|
|
@@ -19,7 +19,6 @@ export class KeyboardController implements IInputController {
|
|
|
19
19
|
onKeyDownListener: (event: KeyboardEvent) => void;
|
|
20
20
|
onKeyUpListener: (event: KeyboardEvent) => void;
|
|
21
21
|
onKeyPressListener: (event: KeyboardEvent) => void;
|
|
22
|
-
onCompositionEndListener: (event: CompositionEvent) => void;
|
|
23
22
|
|
|
24
23
|
constructor(streamMessageController: StreamMessageController, config: Config, activeKeys: ActiveKeys) {
|
|
25
24
|
this.streamMessageController = streamMessageController;
|
|
@@ -29,11 +28,9 @@ export class KeyboardController implements IInputController {
|
|
|
29
28
|
this.onKeyDownListener = this.handleOnKeyDown.bind(this);
|
|
30
29
|
this.onKeyUpListener = this.handleOnKeyUp.bind(this);
|
|
31
30
|
this.onKeyPressListener = this.handleOnKeyPress.bind(this);
|
|
32
|
-
this.onCompositionEndListener = this.handleOnCompositionEnd.bind(this);
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
register() {
|
|
36
|
-
document.addEventListener('compositionend', this.onCompositionEndListener);
|
|
37
34
|
document.addEventListener('keydown', this.onKeyDownListener);
|
|
38
35
|
document.addEventListener('keyup', this.onKeyUpListener);
|
|
39
36
|
//This has been deprecated as at Jun 13 2021
|
|
@@ -41,7 +38,6 @@ export class KeyboardController implements IInputController {
|
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
unregister() {
|
|
44
|
-
document.removeEventListener('compositionend', this.onCompositionEndListener);
|
|
45
41
|
document.removeEventListener('keydown', this.onKeyDownListener);
|
|
46
42
|
document.removeEventListener('keyup', this.onKeyUpListener);
|
|
47
43
|
document.removeEventListener('keypress', this.onKeyPressListener);
|
|
@@ -100,33 +96,6 @@ export class KeyboardController implements IInputController {
|
|
|
100
96
|
toStreamerHandlers.get('KeyPress')?.([keyCode]);
|
|
101
97
|
}
|
|
102
98
|
|
|
103
|
-
private handleOnCompositionEnd(compositionEvent: CompositionEvent) {
|
|
104
|
-
if (compositionEvent.data && compositionEvent.data.length) {
|
|
105
|
-
compositionEvent.data.split('').forEach((char) => {
|
|
106
|
-
// This keydown, keypress, keyup flow is required to mimic the way characters are
|
|
107
|
-
// normally triggered
|
|
108
|
-
this.handleOnKeyDown(
|
|
109
|
-
new KeyboardEvent('keydown', {
|
|
110
|
-
keyCode: char.toUpperCase().charCodeAt(0),
|
|
111
|
-
charCode: char.charCodeAt(0)
|
|
112
|
-
})
|
|
113
|
-
);
|
|
114
|
-
this.handleOnKeyPress(
|
|
115
|
-
new KeyboardEvent('keypress', {
|
|
116
|
-
keyCode: char.toUpperCase().charCodeAt(0),
|
|
117
|
-
charCode: char.charCodeAt(0)
|
|
118
|
-
})
|
|
119
|
-
);
|
|
120
|
-
this.handleOnKeyUp(
|
|
121
|
-
new KeyboardEvent('keyup', {
|
|
122
|
-
keyCode: char.toUpperCase().charCodeAt(0),
|
|
123
|
-
charCode: char.charCodeAt(0)
|
|
124
|
-
})
|
|
125
|
-
);
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
99
|
/**
|
|
131
100
|
* Gets the Keycode of the Key pressed
|
|
132
101
|
* @param keyboardEvent - Key board Event
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
1
2
|
import { MouseButtonsMask, MouseButton } from './MouseButtons';
|
|
2
3
|
import { StreamMessageController } from '../UeInstanceMessage/StreamMessageController';
|
|
3
4
|
import { InputCoordTranslator } from '../Util/InputCoordTranslator';
|
|
@@ -57,22 +58,22 @@ export class MouseController implements IInputController {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
registerMouseEnterAndLeaveEvents() {
|
|
60
|
-
const videoElementParent = this.videoPlayer.getVideoParentElement()
|
|
61
|
-
videoElementParent
|
|
62
|
-
videoElementParent
|
|
61
|
+
const videoElementParent = this.videoPlayer.getVideoParentElement();
|
|
62
|
+
videoElementParent?.addEventListener('mouseenter', this.onEnterListener);
|
|
63
|
+
videoElementParent?.addEventListener('mouseleave', this.onLeaveListener);
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
unregisterMouseEnterAndLeaveEvents() {
|
|
66
|
-
const videoElementParent = this.videoPlayer.getVideoParentElement()
|
|
67
|
-
videoElementParent
|
|
68
|
-
videoElementParent
|
|
67
|
+
const videoElementParent = this.videoPlayer.getVideoParentElement();
|
|
68
|
+
videoElementParent?.removeEventListener('mouseenter', this.onEnterListener);
|
|
69
|
+
videoElementParent?.removeEventListener('mouseleave', this.onLeaveListener);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
private onMouseEnter(event: MouseEvent) {
|
|
72
73
|
if (!this.videoPlayer.isVideoReady()) {
|
|
73
74
|
return;
|
|
74
75
|
}
|
|
75
|
-
this.streamMessageController.toStreamerHandlers.get('MouseEnter')();
|
|
76
|
+
this.streamMessageController.toStreamerHandlers.get('MouseEnter')?.();
|
|
76
77
|
this.pressMouseButtons(event.buttons, event.x, event.y);
|
|
77
78
|
}
|
|
78
79
|
|
|
@@ -80,7 +81,7 @@ export class MouseController implements IInputController {
|
|
|
80
81
|
if (!this.videoPlayer.isVideoReady()) {
|
|
81
82
|
return;
|
|
82
83
|
}
|
|
83
|
-
this.streamMessageController.toStreamerHandlers.get('MouseLeave')();
|
|
84
|
+
this.streamMessageController.toStreamerHandlers.get('MouseLeave')?.();
|
|
84
85
|
this.releaseMouseButtons(event.buttons, event.x, event.y);
|
|
85
86
|
}
|
|
86
87
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
1
2
|
import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
|
|
2
3
|
import { StreamMessageController } from '../UeInstanceMessage/StreamMessageController';
|
|
3
4
|
import { InputCoordTranslator, TranslatedCoordUnsigned } from '../Util/InputCoordTranslator';
|
|
@@ -7,7 +7,6 @@ import { WebRtcPlayerController } from '../WebRtcPlayer/WebRtcPlayerController';
|
|
|
7
7
|
import { Flags, NumericParameters } from '../Config/Config';
|
|
8
8
|
import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
|
|
9
9
|
import { InitialSettings } from '../DataChannel/InitialSettings';
|
|
10
|
-
import { OnScreenKeyboard } from '../UI/OnScreenKeyboard';
|
|
11
10
|
import {
|
|
12
11
|
PixelStreamingEventEmitter,
|
|
13
12
|
InitialSettingsEvent,
|
|
@@ -78,8 +77,6 @@ export class PixelStreaming {
|
|
|
78
77
|
|
|
79
78
|
private allowConsoleCommands = false;
|
|
80
79
|
|
|
81
|
-
private onScreenKeyboardHelper: OnScreenKeyboard;
|
|
82
|
-
|
|
83
80
|
private _videoStartTime: number;
|
|
84
81
|
private _inputController: boolean;
|
|
85
82
|
|
|
@@ -104,13 +101,6 @@ export class PixelStreaming {
|
|
|
104
101
|
// setup WebRTC
|
|
105
102
|
this.setWebRtcPlayerController(new WebRtcPlayerController(this.config, this));
|
|
106
103
|
|
|
107
|
-
// Onscreen keyboard
|
|
108
|
-
this.onScreenKeyboardHelper = new OnScreenKeyboard(this.videoElementParent);
|
|
109
|
-
this.onScreenKeyboardHelper.unquantizeAndDenormalizeUnsigned = (x: number, y: number) =>
|
|
110
|
-
this._webRtcController.requestUnquantizedAndDenormalizeUnsigned(x, y);
|
|
111
|
-
this._activateOnScreenKeyboard = (command: any) =>
|
|
112
|
-
this.onScreenKeyboardHelper.showOnScreenKeyboard(command);
|
|
113
|
-
|
|
114
104
|
this._webXrController = new WebXRController(this._webRtcController);
|
|
115
105
|
|
|
116
106
|
this._setupWebRtcTCPRelayDetection = this._setupWebRtcTCPRelayDetection.bind(this);
|
|
@@ -277,15 +267,6 @@ export class PixelStreaming {
|
|
|
277
267
|
this.config._registerOnChangeEvents(this._eventEmitter);
|
|
278
268
|
}
|
|
279
269
|
|
|
280
|
-
/**
|
|
281
|
-
* Activate the on screen keyboard when receiving the command from the streamer
|
|
282
|
-
* @param command - the keyboard command
|
|
283
|
-
*/
|
|
284
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
285
|
-
_activateOnScreenKeyboard(command: any): void {
|
|
286
|
-
throw new Error('Method not implemented.');
|
|
287
|
-
}
|
|
288
|
-
|
|
289
270
|
/**
|
|
290
271
|
* Set the input control ownership
|
|
291
272
|
* @param inputControlOwnership - does the user have input control ownership
|
|
@@ -819,6 +800,19 @@ export class PixelStreaming {
|
|
|
819
800
|
return true;
|
|
820
801
|
}
|
|
821
802
|
|
|
803
|
+
/**
|
|
804
|
+
* Sets the text contents of the currently focused UE text box widget.
|
|
805
|
+
* @param contents The new contents of the UE text box.
|
|
806
|
+
* @returns True if the message could be sent.
|
|
807
|
+
*/
|
|
808
|
+
public sendTextboxEntry(contents: string): boolean {
|
|
809
|
+
if (!this._webRtcController.videoPlayer.isVideoReady()) {
|
|
810
|
+
return false;
|
|
811
|
+
}
|
|
812
|
+
this._webRtcController.sendTextboxEntry(contents);
|
|
813
|
+
return true;
|
|
814
|
+
}
|
|
815
|
+
|
|
822
816
|
/**
|
|
823
817
|
* Add a UE -> browser response event listener
|
|
824
818
|
* @param name - The name of the response handler
|
|
@@ -81,6 +81,10 @@ export class StreamMessageController {
|
|
|
81
81
|
id: 51,
|
|
82
82
|
structure: ['string']
|
|
83
83
|
});
|
|
84
|
+
this.toStreamerMessages.set('TextboxEntry', {
|
|
85
|
+
id: 52,
|
|
86
|
+
structure: ['string']
|
|
87
|
+
});
|
|
84
88
|
// Keyboard Input Message. Range = 60..69.
|
|
85
89
|
this.toStreamerMessages.set('KeyDown', {
|
|
86
90
|
id: 60,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
|
|
4
|
+
|
|
5
|
+
export class BrowserUtils {
|
|
6
|
+
static getSupportedVideoCodecs(): Array<string> {
|
|
7
|
+
const browserSupportedCodecs: Array<string> = [];
|
|
8
|
+
// Try get the info needed from the RTCRtpReceiver. This is only available on chrome
|
|
9
|
+
if (!RTCRtpReceiver.getCapabilities) {
|
|
10
|
+
Logger.Warning(
|
|
11
|
+
'RTCRtpReceiver.getCapabilities API is not available in your browser, defaulting to guess that we support H.264.'
|
|
12
|
+
);
|
|
13
|
+
browserSupportedCodecs.push(
|
|
14
|
+
'H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f'
|
|
15
|
+
);
|
|
16
|
+
return browserSupportedCodecs;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const matcher = /(VP\d|H26\d|AV1).*/;
|
|
20
|
+
const capabilities = RTCRtpReceiver.getCapabilities('video');
|
|
21
|
+
if (!capabilities) {
|
|
22
|
+
browserSupportedCodecs.push(
|
|
23
|
+
'H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f'
|
|
24
|
+
);
|
|
25
|
+
return browserSupportedCodecs;
|
|
26
|
+
}
|
|
27
|
+
capabilities.codecs.forEach((codec) => {
|
|
28
|
+
const str = codec.mimeType.split('/')[1] + ' ' + (codec.sdpFmtpLine || '');
|
|
29
|
+
const match = matcher.exec(str);
|
|
30
|
+
if (match !== null) {
|
|
31
|
+
browserSupportedCodecs.push(str);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return browserSupportedCodecs;
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/Util/EventEmitter.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
1
2
|
import { FlagsIds, NumericParametersIds, OptionParametersIds, TextParametersIds } from '../Config/Config';
|
|
2
3
|
import { LatencyTestResults } from '../DataChannel/LatencyTestResults';
|
|
3
4
|
import { AggregatedStats } from '../PeerConnectionController/AggregatedStats';
|
|
@@ -427,6 +428,23 @@ export class LatencyCalculatedEvent extends Event {
|
|
|
427
428
|
}
|
|
428
429
|
}
|
|
429
430
|
|
|
431
|
+
/**
|
|
432
|
+
* An event that is emitted when we receive the "onScreenKeyboard" command from UE.
|
|
433
|
+
*/
|
|
434
|
+
export class ShowOnScreenKeyboardEvent extends Event {
|
|
435
|
+
override readonly type: 'showOnScreenKeyboard';
|
|
436
|
+
readonly data: {
|
|
437
|
+
showOnScreenKeyboard: boolean;
|
|
438
|
+
x: number;
|
|
439
|
+
y: number;
|
|
440
|
+
contents: string;
|
|
441
|
+
};
|
|
442
|
+
constructor(data: ShowOnScreenKeyboardEvent['data']) {
|
|
443
|
+
super('showOnScreenKeyboard');
|
|
444
|
+
this.data = data;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
430
448
|
/**
|
|
431
449
|
* An event that is emitted when receiving data channel latency test response from server.
|
|
432
450
|
* This event is handled by DataChannelLatencyTestController
|
|
@@ -616,6 +634,7 @@ export type PixelStreamingEvent =
|
|
|
616
634
|
| DataChannelCloseEvent
|
|
617
635
|
| DataChannelErrorEvent
|
|
618
636
|
| VideoInitializedEvent
|
|
637
|
+
| ShowOnScreenKeyboardEvent
|
|
619
638
|
| StreamLoadingEvent
|
|
620
639
|
| StreamPreConnectEvent
|
|
621
640
|
| StreamReconnectEvent
|
package/src/Util/RTCUtils.ts
CHANGED
|
@@ -70,6 +70,18 @@ export class VideoPlayer {
|
|
|
70
70
|
window.addEventListener('orientationchange', () => this.onOrientationChange());
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
public destroy() {
|
|
74
|
+
this.videoElement.src = '';
|
|
75
|
+
this.videoElement.srcObject = null;
|
|
76
|
+
this.videoElement.remove();
|
|
77
|
+
|
|
78
|
+
if (this.audioElement) {
|
|
79
|
+
this.audioElement.src = '';
|
|
80
|
+
this.audioElement.srcObject = null;
|
|
81
|
+
this.audioElement.remove();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
73
85
|
public setAudioElement(audioElement: HTMLAudioElement): void {
|
|
74
86
|
this.audioElement = audioElement;
|
|
75
87
|
}
|
|
@@ -117,8 +129,8 @@ export class VideoPlayer {
|
|
|
117
129
|
* Get the current context of the html video elements parent
|
|
118
130
|
* @returns - the current context of the video elements parent
|
|
119
131
|
*/
|
|
120
|
-
getVideoParentElement(): HTMLElement {
|
|
121
|
-
return this.videoElement.parentElement;
|
|
132
|
+
getVideoParentElement(): HTMLElement | undefined {
|
|
133
|
+
return this.videoElement.parentElement ?? undefined;
|
|
122
134
|
}
|
|
123
135
|
|
|
124
136
|
/**
|
|
@@ -34,7 +34,7 @@ import { ResponseController } from '../UeInstanceMessage/ResponseController';
|
|
|
34
34
|
import { SendMessageController } from '../UeInstanceMessage/SendMessageController';
|
|
35
35
|
import { ToStreamerMessagesController } from '../UeInstanceMessage/ToStreamerMessagesController';
|
|
36
36
|
import { DataChannelSender } from '../DataChannel/DataChannelSender';
|
|
37
|
-
import { InputCoordTranslator
|
|
37
|
+
import { InputCoordTranslator } from '../Util/InputCoordTranslator';
|
|
38
38
|
import { PixelStreaming } from '../PixelStreaming/PixelStreaming';
|
|
39
39
|
import {
|
|
40
40
|
DataChannelCloseEvent,
|
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
PlayStreamErrorEvent,
|
|
46
46
|
PlayStreamEvent,
|
|
47
47
|
PlayStreamRejectedEvent,
|
|
48
|
+
ShowOnScreenKeyboardEvent,
|
|
48
49
|
StreamerListMessageEvent,
|
|
49
50
|
StreamerIDChangedMessageEvent
|
|
50
51
|
} from '../Util/EventEmitter';
|
|
@@ -56,6 +57,7 @@ import { IURLSearchParams } from '../Util/IURLSearchParams';
|
|
|
56
57
|
import { IInputController } from '../Inputs/IInputController';
|
|
57
58
|
import { GamepadController } from '../Inputs/GamepadController';
|
|
58
59
|
import { LatencyInfo } from '../PeerConnectionController/LatencyCalculator';
|
|
60
|
+
import { BrowserUtils } from '../Util/BrowserUtils';
|
|
59
61
|
|
|
60
62
|
/**
|
|
61
63
|
* Entry point for the WebRTC Player
|
|
@@ -232,6 +234,11 @@ export class WebRtcPlayerController {
|
|
|
232
234
|
|
|
233
235
|
this.forceReconnect = false;
|
|
234
236
|
|
|
237
|
+
// Reset the list of all possible codecs on disconnect so that if the next connection has "NegotiateCodecs" on
|
|
238
|
+
// then all codecs can be negotiated
|
|
239
|
+
this.config.getSettingOption(OptionParameters.PreferredCodec).options =
|
|
240
|
+
BrowserUtils.getSupportedVideoCodecs();
|
|
241
|
+
|
|
235
242
|
this.pixelStreaming._onDisconnect(disconnectMessage, allowClickToReconnect);
|
|
236
243
|
|
|
237
244
|
this.afkController.stopAfkWarningTimer();
|
|
@@ -335,12 +342,11 @@ export class WebRtcPlayerController {
|
|
|
335
342
|
}
|
|
336
343
|
|
|
337
344
|
/**
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
* @param y y axis coordinate
|
|
345
|
+
* Destroys the video player and makes sure resources are freed. This helps to prevent the issue in chrome
|
|
346
|
+
* where it refuses to make new video players.
|
|
341
347
|
*/
|
|
342
|
-
|
|
343
|
-
|
|
348
|
+
destroyVideoPlayer() {
|
|
349
|
+
this.videoPlayer.destroy();
|
|
344
350
|
}
|
|
345
351
|
|
|
346
352
|
/**
|
|
@@ -700,11 +706,23 @@ export class WebRtcPlayerController {
|
|
|
700
706
|
|
|
701
707
|
Logger.Info('Data Channel Command: ' + commandAsString);
|
|
702
708
|
const command = JSON.parse(commandAsString);
|
|
709
|
+
|
|
710
|
+
// Handle "onScreenKeyboard" event
|
|
703
711
|
if (command.command === 'onScreenKeyboard') {
|
|
704
|
-
this.
|
|
712
|
+
this.handleOnScreenKeyboardCommand(command);
|
|
705
713
|
}
|
|
706
714
|
}
|
|
707
715
|
|
|
716
|
+
handleOnScreenKeyboardCommand(command: any) {
|
|
717
|
+
const data: ShowOnScreenKeyboardEvent['data'] = {
|
|
718
|
+
showOnScreenKeyboard: command.showOnScreenKeyboard ?? true,
|
|
719
|
+
x: command.x ?? 0,
|
|
720
|
+
y: command.y ?? 0,
|
|
721
|
+
contents: command.contents ?? ''
|
|
722
|
+
};
|
|
723
|
+
this.pixelStreaming.dispatchEvent(new ShowOnScreenKeyboardEvent(data));
|
|
724
|
+
}
|
|
725
|
+
|
|
708
726
|
/**
|
|
709
727
|
* Handles a protocol message received from the streamer
|
|
710
728
|
* @param message the message data from the streamer
|
|
@@ -1762,6 +1780,15 @@ export class WebRtcPlayerController {
|
|
|
1762
1780
|
this.toStreamerMessagesController.SendRequestQualityControl();
|
|
1763
1781
|
}
|
|
1764
1782
|
|
|
1783
|
+
/**
|
|
1784
|
+
* Send a `TextBoxEntry` message back to UE.
|
|
1785
|
+
* @param contents The new contents of the UE side text box.
|
|
1786
|
+
*/
|
|
1787
|
+
sendTextboxEntry(contents: string) {
|
|
1788
|
+
Logger.Info('---- Sending TextboxEntry message ----');
|
|
1789
|
+
this.streamMessageController.toStreamerHandlers.get('TextboxEntry')?.([contents]);
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1765
1792
|
/**
|
|
1766
1793
|
* Handles when a Latency Test Result are received from the UE Instance
|
|
1767
1794
|
* @param message - Latency Test Timings
|
package/tsconfig.cjs.json
CHANGED
package/tsconfig.esm.json
CHANGED
package/tsconfig.jest.json
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"noImplicitReturns": true,
|
|
13
13
|
"noPropertyAccessFromIndexSignature": true,
|
|
14
14
|
"declaration": true,
|
|
15
|
-
"declarationDir": "./dist/types"
|
|
15
|
+
"declarationDir": "./dist/types",
|
|
16
|
+
"moduleResolution": "bundler" // helps IDEs
|
|
16
17
|
},
|
|
17
18
|
"lib": ["ES6"],
|
|
18
19
|
"include": ["./src/**/*.ts"],
|