@epicgames-ps/lib-pixelstreamingfrontend-ue5.5 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/dist/commonjs/AFK/AFKController.js +109 -109
  2. package/dist/commonjs/Config/Config.js +559 -559
  3. package/dist/commonjs/Config/SettingBase.js +98 -98
  4. package/dist/commonjs/Config/SettingFlag.js +49 -49
  5. package/dist/commonjs/Config/SettingNumber.js +83 -83
  6. package/dist/commonjs/Config/SettingOption.js +84 -84
  7. package/dist/commonjs/Config/SettingText.js +42 -42
  8. package/dist/commonjs/DataChannel/DataChannelController.js +106 -106
  9. package/dist/commonjs/DataChannel/DataChannelLatencyTestController.js +94 -94
  10. package/dist/commonjs/DataChannel/DataChannelLatencyTestResults.js +18 -18
  11. package/dist/commonjs/DataChannel/DataChannelSender.js +43 -43
  12. package/dist/commonjs/DataChannel/InitialSettings.js +41 -41
  13. package/dist/commonjs/DataChannel/LatencyTestResults.js +60 -60
  14. package/dist/commonjs/FreezeFrame/FreezeFrame.js +93 -93
  15. package/dist/commonjs/FreezeFrame/FreezeFrameController.js +95 -95
  16. package/dist/commonjs/Inputs/GamepadController.js +188 -188
  17. package/dist/commonjs/Inputs/GamepadTypes.js +21 -21
  18. package/dist/commonjs/Inputs/IInputController.js +2 -2
  19. package/dist/commonjs/Inputs/InputClassesFactory.js +96 -96
  20. package/dist/commonjs/Inputs/KeyCodes.js +112 -112
  21. package/dist/commonjs/Inputs/KeyboardController.js +137 -137
  22. package/dist/commonjs/Inputs/MouseButtons.js +28 -28
  23. package/dist/commonjs/Inputs/MouseController.js +97 -97
  24. package/dist/commonjs/Inputs/MouseControllerHovering.js +93 -93
  25. package/dist/commonjs/Inputs/MouseControllerLocked.js +153 -153
  26. package/dist/commonjs/Inputs/SpecialKeyCodes.js +19 -19
  27. package/dist/commonjs/Inputs/TouchController.js +123 -123
  28. package/dist/commonjs/Inputs/TouchController.js.map +1 -1
  29. package/dist/commonjs/Inputs/TouchControllerFake.js +91 -91
  30. package/dist/commonjs/Inputs/XRGamepadController.js +124 -124
  31. package/dist/commonjs/PeerConnectionController/AggregatedStats.js +252 -252
  32. package/dist/commonjs/PeerConnectionController/CandidatePairStats.js +10 -10
  33. package/dist/commonjs/PeerConnectionController/CandidateStat.js +10 -10
  34. package/dist/commonjs/PeerConnectionController/CodecStats.js +10 -10
  35. package/dist/commonjs/PeerConnectionController/DataChannelStats.js +10 -10
  36. package/dist/commonjs/PeerConnectionController/InboundRTPStats.js +22 -22
  37. package/dist/commonjs/PeerConnectionController/InboundTrackStats.js +10 -10
  38. package/dist/commonjs/PeerConnectionController/OutBoundRTPStats.js +16 -16
  39. package/dist/commonjs/PeerConnectionController/PeerConnectionController.js +584 -584
  40. package/dist/commonjs/PeerConnectionController/SessionStats.js +10 -10
  41. package/dist/commonjs/PeerConnectionController/StreamStats.js +10 -10
  42. package/dist/commonjs/PixelStreaming/PixelStreaming.js +607 -607
  43. package/dist/commonjs/UI/OnScreenKeyboard.js +82 -82
  44. package/dist/commonjs/UeInstanceMessage/ResponseController.js +38 -38
  45. package/dist/commonjs/UeInstanceMessage/SendMessageController.js +120 -120
  46. package/dist/commonjs/UeInstanceMessage/StreamMessageController.js +210 -210
  47. package/dist/commonjs/UeInstanceMessage/ToStreamerMessagesController.js +49 -49
  48. package/dist/commonjs/Util/EventEmitter.js +386 -386
  49. package/dist/commonjs/Util/FileUtil.js +108 -108
  50. package/dist/commonjs/Util/IURLSearchParams.js +25 -25
  51. package/dist/commonjs/Util/InputCoordTranslator.js +49 -49
  52. package/dist/commonjs/Util/RTCUtils.js +40 -40
  53. package/dist/commonjs/VideoPlayer/StreamController.js +67 -67
  54. package/dist/commonjs/VideoPlayer/VideoPlayer.js +177 -177
  55. package/dist/commonjs/WebRtcPlayer/WebRtcPlayerController.js +1221 -1221
  56. package/dist/commonjs/WebXR/WebXRController.js +335 -335
  57. package/dist/commonjs/pixelstreamingfrontend.js +70 -70
  58. package/dist/esm/AFK/AFKController.js +105 -105
  59. package/dist/esm/Config/Config.js +551 -551
  60. package/dist/esm/Config/SettingBase.js +94 -94
  61. package/dist/esm/Config/SettingFlag.js +45 -45
  62. package/dist/esm/Config/SettingNumber.js +79 -79
  63. package/dist/esm/Config/SettingOption.js +80 -80
  64. package/dist/esm/Config/SettingText.js +38 -38
  65. package/dist/esm/DataChannel/DataChannelController.js +102 -102
  66. package/dist/esm/DataChannel/DataChannelLatencyTestController.js +90 -90
  67. package/dist/esm/DataChannel/DataChannelLatencyTestResults.js +14 -14
  68. package/dist/esm/DataChannel/DataChannelSender.js +39 -39
  69. package/dist/esm/DataChannel/InitialSettings.js +34 -34
  70. package/dist/esm/DataChannel/LatencyTestResults.js +56 -56
  71. package/dist/esm/FreezeFrame/FreezeFrame.js +89 -89
  72. package/dist/esm/FreezeFrame/FreezeFrameController.js +91 -91
  73. package/dist/esm/Inputs/GamepadController.js +184 -184
  74. package/dist/esm/Inputs/GamepadTypes.js +17 -17
  75. package/dist/esm/Inputs/IInputController.js +1 -1
  76. package/dist/esm/Inputs/InputClassesFactory.js +91 -91
  77. package/dist/esm/Inputs/KeyCodes.js +109 -109
  78. package/dist/esm/Inputs/KeyboardController.js +133 -133
  79. package/dist/esm/Inputs/MouseButtons.js +23 -23
  80. package/dist/esm/Inputs/MouseController.js +93 -93
  81. package/dist/esm/Inputs/MouseControllerHovering.js +89 -89
  82. package/dist/esm/Inputs/MouseControllerLocked.js +149 -149
  83. package/dist/esm/Inputs/SpecialKeyCodes.js +15 -15
  84. package/dist/esm/Inputs/TouchController.js +119 -119
  85. package/dist/esm/Inputs/TouchController.js.map +1 -1
  86. package/dist/esm/Inputs/TouchControllerFake.js +87 -87
  87. package/dist/esm/Inputs/XRGamepadController.js +120 -120
  88. package/dist/esm/PeerConnectionController/AggregatedStats.js +248 -248
  89. package/dist/esm/PeerConnectionController/CandidatePairStats.js +6 -6
  90. package/dist/esm/PeerConnectionController/CandidateStat.js +6 -6
  91. package/dist/esm/PeerConnectionController/CodecStats.js +6 -6
  92. package/dist/esm/PeerConnectionController/DataChannelStats.js +6 -6
  93. package/dist/esm/PeerConnectionController/InboundRTPStats.js +16 -16
  94. package/dist/esm/PeerConnectionController/InboundTrackStats.js +6 -6
  95. package/dist/esm/PeerConnectionController/OutBoundRTPStats.js +11 -11
  96. package/dist/esm/PeerConnectionController/PeerConnectionController.js +580 -580
  97. package/dist/esm/PeerConnectionController/SessionStats.js +6 -6
  98. package/dist/esm/PeerConnectionController/StreamStats.js +6 -6
  99. package/dist/esm/PixelStreaming/PixelStreaming.js +603 -603
  100. package/dist/esm/UI/OnScreenKeyboard.js +78 -78
  101. package/dist/esm/UeInstanceMessage/ResponseController.js +34 -34
  102. package/dist/esm/UeInstanceMessage/SendMessageController.js +116 -116
  103. package/dist/esm/UeInstanceMessage/StreamMessageController.js +205 -205
  104. package/dist/esm/UeInstanceMessage/ToStreamerMessagesController.js +45 -45
  105. package/dist/esm/Util/EventEmitter.js +345 -345
  106. package/dist/esm/Util/FileUtil.js +103 -103
  107. package/dist/esm/Util/IURLSearchParams.js +21 -21
  108. package/dist/esm/Util/InputCoordTranslator.js +45 -45
  109. package/dist/esm/Util/RTCUtils.js +36 -36
  110. package/dist/esm/VideoPlayer/StreamController.js +63 -63
  111. package/dist/esm/VideoPlayer/VideoPlayer.js +173 -173
  112. package/dist/esm/WebRtcPlayer/WebRtcPlayerController.js +1217 -1217
  113. package/dist/esm/WebXR/WebXRController.js +331 -331
  114. package/dist/esm/pixelstreamingfrontend.js +24 -24
  115. package/dist/types/AFK/AFKController.d.ts +38 -38
  116. package/dist/types/Config/Config.d.ts +220 -220
  117. package/dist/types/Config/SettingBase.d.ts +43 -43
  118. package/dist/types/Config/SettingFlag.d.ts +24 -24
  119. package/dist/types/Config/SettingNumber.d.ts +41 -41
  120. package/dist/types/Config/SettingOption.d.ts +41 -41
  121. package/dist/types/Config/SettingText.d.ts +21 -21
  122. package/dist/types/DataChannel/DataChannelController.d.ts +59 -59
  123. package/dist/types/DataChannel/DataChannelLatencyTestController.d.ts +25 -25
  124. package/dist/types/DataChannel/DataChannelLatencyTestResults.d.ts +46 -46
  125. package/dist/types/DataChannel/DataChannelSender.d.ts +21 -21
  126. package/dist/types/DataChannel/InitialSettings.d.ts +44 -44
  127. package/dist/types/DataChannel/LatencyTestResults.d.ts +31 -31
  128. package/dist/types/FreezeFrame/FreezeFrame.d.ts +36 -36
  129. package/dist/types/FreezeFrame/FreezeFrameController.d.ts +37 -37
  130. package/dist/types/Inputs/GamepadController.d.ts +61 -61
  131. package/dist/types/Inputs/GamepadTypes.d.ts +15 -15
  132. package/dist/types/Inputs/IInputController.d.ts +16 -16
  133. package/dist/types/Inputs/InputClassesFactory.d.ts +53 -53
  134. package/dist/types/Inputs/KeyCodes.d.ts +5 -5
  135. package/dist/types/Inputs/KeyboardController.d.ts +34 -34
  136. package/dist/types/Inputs/MouseButtons.d.ts +22 -22
  137. package/dist/types/Inputs/MouseController.d.ts +40 -40
  138. package/dist/types/Inputs/MouseControllerHovering.d.ts +26 -26
  139. package/dist/types/Inputs/MouseControllerLocked.d.ts +31 -31
  140. package/dist/types/Inputs/SpecialKeyCodes.d.ts +14 -14
  141. package/dist/types/Inputs/TouchController.d.ts +28 -28
  142. package/dist/types/Inputs/TouchControllerFake.d.ts +29 -29
  143. package/dist/types/Inputs/XRGamepadController.d.ts +15 -15
  144. package/dist/types/PeerConnectionController/AggregatedStats.d.ts +82 -82
  145. package/dist/types/PeerConnectionController/CandidatePairStats.d.ts +22 -22
  146. package/dist/types/PeerConnectionController/CandidateStat.d.ts +13 -13
  147. package/dist/types/PeerConnectionController/CodecStats.d.ts +14 -14
  148. package/dist/types/PeerConnectionController/DataChannelStats.d.ts +15 -15
  149. package/dist/types/PeerConnectionController/InboundRTPStats.d.ts +141 -141
  150. package/dist/types/PeerConnectionController/InboundTrackStats.d.ts +32 -32
  151. package/dist/types/PeerConnectionController/OutBoundRTPStats.d.ts +23 -23
  152. package/dist/types/PeerConnectionController/PeerConnectionController.d.ts +143 -143
  153. package/dist/types/PeerConnectionController/SessionStats.d.ts +8 -8
  154. package/dist/types/PeerConnectionController/StreamStats.d.ts +9 -9
  155. package/dist/types/PixelStreaming/PixelStreaming.d.ts +271 -271
  156. package/dist/types/UI/OnScreenKeyboard.d.ts +30 -30
  157. package/dist/types/UeInstanceMessage/ResponseController.d.ts +19 -19
  158. package/dist/types/UeInstanceMessage/SendMessageController.d.ts +18 -18
  159. package/dist/types/UeInstanceMessage/StreamMessageController.d.ts +29 -29
  160. package/dist/types/UeInstanceMessage/ToStreamerMessagesController.d.ts +32 -32
  161. package/dist/types/Util/EventEmitter.d.ts +429 -429
  162. package/dist/types/Util/FileUtil.d.ts +32 -32
  163. package/dist/types/Util/IURLSearchParams.d.ts +9 -9
  164. package/dist/types/Util/InputCoordTranslator.d.ts +29 -29
  165. package/dist/types/Util/RTCUtils.d.ts +8 -8
  166. package/dist/types/VideoPlayer/StreamController.d.ts +22 -22
  167. package/dist/types/VideoPlayer/VideoPlayer.d.ts +78 -78
  168. package/dist/types/WebRtcPlayer/WebRtcPlayerController.d.ts +379 -379
  169. package/dist/types/WebXR/WebXRController.d.ts +42 -42
  170. package/dist/types/pixelstreamingfrontend.d.ts +23 -23
  171. package/package.json +45 -45
  172. package/src/Inputs/TouchController.ts +3 -3
@@ -1,604 +1,604 @@
1
- // Copyright Epic Games, Inc. All Rights Reserved.
2
- import { OptionParameters } from '../Config/Config';
3
- import { WebRtcPlayerController } from '../WebRtcPlayer/WebRtcPlayerController';
4
- import { Flags, NumericParameters } from '../Config/Config';
5
- import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
6
- import { OnScreenKeyboard } from '../UI/OnScreenKeyboard';
7
- import { EventEmitter, InitialSettingsEvent, LatencyTestResultEvent, StatsReceivedEvent, StreamLoadingEvent, StreamPreConnectEvent, StreamReconnectEvent, StreamPreDisconnectEvent, VideoEncoderAvgQPEvent, VideoInitializedEvent, WebRtcAutoConnectEvent, WebRtcConnectedEvent, WebRtcConnectingEvent, WebRtcDisconnectedEvent, WebRtcFailedEvent, WebRtcSdpEvent, DataChannelLatencyTestResponseEvent, DataChannelLatencyTestResultEvent, PlayerCountEvent, WebRtcTCPRelayDetectedEvent } from '../Util/EventEmitter';
8
- import { WebXRController } from '../WebXR/WebXRController';
9
- import { MessageDirection } from '../UeInstanceMessage/StreamMessageController';
10
- import { DataChannelLatencyTestController } from '../DataChannel/DataChannelLatencyTestController';
11
- import { RTCUtils } from '../Util/RTCUtils';
12
- import { IURLSearchParams } from '../Util/IURLSearchParams';
13
- /**
14
- * The key class for the browser side of a Pixel Streaming application, it includes:
15
- * WebRTC handling, XR support, input handling, and emitters for lifetime and state change events.
16
- * Users are encouraged to use this class as is, through composition, or extend it. In any case,
17
- * this will likely be the core of your Pixel Streaming experience in terms of functionality.
18
- */
19
- export class PixelStreaming {
20
- /**
21
- * @param config - A newly instantiated config object
22
- * @param overrides - Parameters to override default behaviour
23
- * returns the base Pixel streaming object
24
- */
25
- constructor(config, overrides) {
26
- this.allowConsoleCommands = false;
27
- this.config = config;
28
- if (overrides === null || overrides === void 0 ? void 0 : overrides.videoElementParent) {
29
- this._videoElementParent = overrides.videoElementParent;
30
- }
31
- this._eventEmitter = new EventEmitter();
32
- this.configureSettings();
33
- // setup WebRTC
34
- this.setWebRtcPlayerController(new WebRtcPlayerController(this.config, this));
35
- // Onscreen keyboard
36
- this.onScreenKeyboardHelper = new OnScreenKeyboard(this.videoElementParent);
37
- this.onScreenKeyboardHelper.unquantizeAndDenormalizeUnsigned = (x, y) => this._webRtcController.requestUnquantizedAndDenormalizeUnsigned(x, y);
38
- this._activateOnScreenKeyboard = (command) => this.onScreenKeyboardHelper.showOnScreenKeyboard(command);
39
- this._webXrController = new WebXRController(this._webRtcController);
40
- this._setupWebRtcTCPRelayDetection = this._setupWebRtcTCPRelayDetection.bind(this);
41
- // Add event listener for the webRtcConnected event
42
- this._eventEmitter.addEventListener('webRtcConnected', (_) => {
43
- // Bind to the stats received event
44
- this._eventEmitter.addEventListener('statsReceived', this._setupWebRtcTCPRelayDetection);
45
- });
46
- }
47
- /**
48
- * Gets the element that contains the video stream element.
49
- */
50
- get videoElementParent() {
51
- if (!this._videoElementParent) {
52
- this._videoElementParent = document.createElement('div');
53
- this._videoElementParent.id = 'videoElementParent';
54
- }
55
- return this._videoElementParent;
56
- }
57
- /**
58
- * Configure the settings with on change listeners and any additional per experience settings.
59
- */
60
- configureSettings() {
61
- this.config._addOnSettingChangedListener(Flags.IsQualityController, (wantsQualityController) => {
62
- // If the setting has been set to true (either programmatically or the user has flicked the toggle)
63
- // and we aren't currently quality controller, send the request
64
- if (wantsQualityController === true && !this._webRtcController.isQualityController) {
65
- this._webRtcController.sendRequestQualityControlOwnership();
66
- }
67
- });
68
- this.config._addOnSettingChangedListener(Flags.AFKDetection, (isAFKEnabled) => {
69
- this._webRtcController.setAfkEnabled(isAFKEnabled);
70
- });
71
- this.config._addOnSettingChangedListener(Flags.MatchViewportResolution, () => {
72
- this._webRtcController.videoPlayer.updateVideoStreamSize();
73
- });
74
- this.config._addOnSettingChangedListener(Flags.HoveringMouseMode, (isHoveringMouse) => {
75
- this.config.setFlagLabel(Flags.HoveringMouseMode, `Control Scheme: ${isHoveringMouse ? 'Hovering' : 'Locked'} Mouse`);
76
- this._webRtcController.setMouseInputEnabled(this.config.isFlagEnabled(Flags.MouseInput));
77
- });
78
- // user input
79
- this.config._addOnSettingChangedListener(Flags.KeyboardInput, (isEnabled) => {
80
- this._webRtcController.setKeyboardInputEnabled(isEnabled);
81
- });
82
- this.config._addOnSettingChangedListener(Flags.MouseInput, (isEnabled) => {
83
- this._webRtcController.setMouseInputEnabled(isEnabled);
84
- });
85
- this.config._addOnSettingChangedListener(Flags.FakeMouseWithTouches, (_isFakeMouseEnabled) => {
86
- this._webRtcController.setTouchInputEnabled(this.config.isFlagEnabled(Flags.TouchInput));
87
- });
88
- this.config._addOnSettingChangedListener(Flags.TouchInput, (isEnabled) => {
89
- this._webRtcController.setTouchInputEnabled(isEnabled);
90
- });
91
- this.config._addOnSettingChangedListener(Flags.GamepadInput, (isEnabled) => {
92
- this._webRtcController.setGamePadInputEnabled(isEnabled);
93
- });
94
- // encoder settings
95
- this.config._addOnNumericSettingChangedListener(NumericParameters.MinQP, (newValue) => {
96
- Logger.Info('-------- Sending MinQP --------');
97
- this._webRtcController.sendEncoderMinQP(newValue);
98
- Logger.Info('-------------------------------------------');
99
- });
100
- this.config._addOnNumericSettingChangedListener(NumericParameters.MaxQP, (newValue) => {
101
- Logger.Info('-------- Sending encoder settings --------');
102
- this._webRtcController.sendEncoderMaxQP(newValue);
103
- Logger.Info('-------------------------------------------');
104
- });
105
- // WebRTC settings
106
- this.config._addOnNumericSettingChangedListener(NumericParameters.WebRTCMinBitrate, (newValue) => {
107
- Logger.Info('-------- Sending web rtc settings --------');
108
- this._webRtcController.sendWebRTCMinBitrate(newValue * 1000 /* kbps to bps */);
109
- Logger.Info('-------------------------------------------');
110
- });
111
- this.config._addOnNumericSettingChangedListener(NumericParameters.WebRTCMaxBitrate, (newValue) => {
112
- Logger.Info('-------- Sending web rtc settings --------');
113
- this._webRtcController.sendWebRTCMaxBitrate(newValue * 1000 /* kbps to bps */);
114
- Logger.Info('-------------------------------------------');
115
- });
116
- this.config._addOnNumericSettingChangedListener(NumericParameters.WebRTCFPS, (newValue) => {
117
- Logger.Info('-------- Sending web rtc settings --------');
118
- this._webRtcController.sendWebRTCFps(newValue);
119
- Logger.Info('-------------------------------------------');
120
- });
121
- this.config._addOnOptionSettingChangedListener(OptionParameters.PreferredCodec, (newValue) => {
122
- if (this._webRtcController) {
123
- this._webRtcController.setPreferredCodec(newValue);
124
- }
125
- });
126
- this.config._registerOnChangeEvents(this._eventEmitter);
127
- }
128
- /**
129
- * Activate the on screen keyboard when receiving the command from the streamer
130
- * @param command - the keyboard command
131
- */
132
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
133
- _activateOnScreenKeyboard(command) {
134
- throw new Error('Method not implemented.');
135
- }
136
- /**
137
- * Set the input control ownership
138
- * @param inputControlOwnership - does the user have input control ownership
139
- */
140
- _onInputControlOwnership(inputControlOwnership) {
141
- this._inputController = inputControlOwnership;
142
- }
143
- /**
144
- * Instantiate the WebRTCPlayerController interface to provide WebRTCPlayerController functionality within this class and set up anything that requires it
145
- * @param webRtcPlayerController - a WebRtcPlayerController controller instance
146
- */
147
- setWebRtcPlayerController(webRtcPlayerController) {
148
- this._webRtcController = webRtcPlayerController;
149
- this._webRtcController.setPreferredCodec(this.config.getSettingOption(OptionParameters.PreferredCodec).selected);
150
- this._webRtcController.resizePlayerStyle();
151
- // connect if auto connect flag is enabled
152
- this.checkForAutoConnect();
153
- }
154
- /**
155
- * Connect to signaling server.
156
- */
157
- connect() {
158
- this._eventEmitter.dispatchEvent(new StreamPreConnectEvent());
159
- this._webRtcController.connectToSignallingServer();
160
- }
161
- /**
162
- * Reconnects to the signaling server. If connection is up, disconnects first
163
- * before establishing a new connection
164
- */
165
- reconnect() {
166
- this._eventEmitter.dispatchEvent(new StreamReconnectEvent());
167
- this._webRtcController.tryReconnect('Reconnecting...');
168
- }
169
- /**
170
- * Disconnect from the signaling server and close open peer connections.
171
- */
172
- disconnect() {
173
- this._eventEmitter.dispatchEvent(new StreamPreDisconnectEvent());
174
- this._webRtcController.close();
175
- }
176
- /**
177
- * Play the stream. Can be called only after a peer connection has been established.
178
- */
179
- play() {
180
- this._onStreamLoading();
181
- this._webRtcController.playStream();
182
- }
183
- /**
184
- * Auto connect if AutoConnect flag is enabled
185
- */
186
- checkForAutoConnect() {
187
- // set up if the auto play will be used or regular click to start
188
- if (this.config.isFlagEnabled(Flags.AutoConnect)) {
189
- // if autoplaying show an info overlay while while waiting for the connection to begin
190
- this._onWebRtcAutoConnect();
191
- this._webRtcController.connectToSignallingServer();
192
- }
193
- }
194
- /**
195
- * Will unmute the microphone track which is sent to Unreal Engine.
196
- * By default, will only unmute an existing mic track.
197
- *
198
- * @param forceEnable Can be used for cases when this object wasn't initialized with a mic track.
199
- * If this parameter is true, the connection will be restarted with a microphone.
200
- * Warning: this takes some time, as a full renegotiation and reconnection will happen.
201
- */
202
- unmuteMicrophone(forceEnable = false) {
203
- // If there's an existing mic track, we just set muted state
204
- if (this.config.isFlagEnabled('UseMic')) {
205
- this.setMicrophoneMuted(false);
206
- return;
207
- }
208
- // If there's no pre-existing mic track, and caller is ok with full reset, we enable and reset
209
- if (forceEnable) {
210
- this.config.setFlagEnabled('UseMic', true);
211
- this.reconnect();
212
- return;
213
- }
214
- // If we prefer not to force a reconnection, just warn the user that this operation didn't happen
215
- Logger.Warning('Trying to unmute mic, but PixelStreaming was initialized with no microphone track. Call with forceEnable == true to re-connect with a mic track.');
216
- }
217
- muteMicrophone() {
218
- if (this.config.isFlagEnabled('UseMic')) {
219
- this.setMicrophoneMuted(true);
220
- return;
221
- }
222
- // If there wasn't a mic track, just let user know there's nothing to mute
223
- Logger.Info('Trying to mute mic, but PixelStreaming has no microphone track, so sending sound is already disabled.');
224
- }
225
- setMicrophoneMuted(mute) {
226
- var _a, _b, _c, _d;
227
- for (const transceiver of (_d = (_c = (_b = (_a = this._webRtcController) === null || _a === void 0 ? void 0 : _a.peerConnectionController) === null || _b === void 0 ? void 0 : _b.peerConnection) === null || _c === void 0 ? void 0 : _c.getTransceivers()) !== null && _d !== void 0 ? _d : []) {
228
- if (RTCUtils.canTransceiverSendAudio(transceiver)) {
229
- transceiver.sender.track.enabled = !mute;
230
- }
231
- }
232
- }
233
- /**
234
- * Will unmute the video track which is sent to Unreal Engine.
235
- * By default, will only unmute an existing video track.
236
- *
237
- * @param forceEnable Can be used for cases when this object wasn't initialized with a video track.
238
- * If this parameter is true, the connection will be restarted with a camera.
239
- * Warning: this takes some time, as a full renegotiation and reconnection will happen.
240
- */
241
- unmuteCamera(forceEnable = false) {
242
- // If there's an existing video track, we just set muted state
243
- if (this.config.isFlagEnabled('UseCamera')) {
244
- this.setCameraMuted(false);
245
- return;
246
- }
247
- // If there's no pre-existing video track, and caller is ok with full reset, we enable and reset
248
- if (forceEnable) {
249
- this.config.setFlagEnabled('UseCamera', true);
250
- this.reconnect();
251
- return;
252
- }
253
- // If we prefer not to force a reconnection, just warn the user that this operation didn't happen
254
- Logger.Warning('Trying to unmute video, but PixelStreaming was initialized with no video track. Call with forceEnable == true to re-connect with a video track.');
255
- }
256
- muteCamera() {
257
- if (this.config.isFlagEnabled('UseCamera')) {
258
- this.setCameraMuted(true);
259
- return;
260
- }
261
- // If there wasn't a mic track, just let user know there's nothing to mute
262
- Logger.Info('Trying to mute camera, but PixelStreaming has no video track, so sending video is already disabled.');
263
- }
264
- setCameraMuted(mute) {
265
- var _a, _b, _c, _d;
266
- for (const transceiver of (_d = (_c = (_b = (_a = this._webRtcController) === null || _a === void 0 ? void 0 : _a.peerConnectionController) === null || _b === void 0 ? void 0 : _b.peerConnection) === null || _c === void 0 ? void 0 : _c.getTransceivers()) !== null && _d !== void 0 ? _d : []) {
267
- if (RTCUtils.canTransceiverSendVideo(transceiver)) {
268
- transceiver.sender.track.enabled = !mute;
269
- }
270
- }
271
- }
272
- /**
273
- * Emit an event on auto connecting
274
- */
275
- _onWebRtcAutoConnect() {
276
- this._eventEmitter.dispatchEvent(new WebRtcAutoConnectEvent());
277
- }
278
- /**
279
- * Set up functionality to happen when receiving a webRTC answer
280
- */
281
- _onWebRtcSdp() {
282
- this._eventEmitter.dispatchEvent(new WebRtcSdpEvent());
283
- }
284
- /**
285
- * Emits a StreamLoading event
286
- */
287
- _onStreamLoading() {
288
- this._eventEmitter.dispatchEvent(new StreamLoadingEvent());
289
- }
290
- /**
291
- * Event fired when the video is disconnected - emits given eventString or an override
292
- * message from webRtcController if one has been set
293
- * @param eventString - a string describing why the connection closed
294
- * @param allowClickToReconnect - true if we want to allow the user to retry the connection with a click
295
- */
296
- _onDisconnect(eventString, allowClickToReconnect) {
297
- this._eventEmitter.dispatchEvent(new WebRtcDisconnectedEvent({
298
- eventString: eventString,
299
- allowClickToReconnect: allowClickToReconnect
300
- }));
301
- }
302
- /**
303
- * Handles when Web Rtc is connecting
304
- */
305
- _onWebRtcConnecting() {
306
- this._eventEmitter.dispatchEvent(new WebRtcConnectingEvent());
307
- }
308
- /**
309
- * Handles when Web Rtc has connected
310
- */
311
- _onWebRtcConnected() {
312
- this._eventEmitter.dispatchEvent(new WebRtcConnectedEvent());
313
- }
314
- /**
315
- * Handles when Web Rtc fails to connect
316
- */
317
- _onWebRtcFailed() {
318
- this._eventEmitter.dispatchEvent(new WebRtcFailedEvent());
319
- }
320
- /**
321
- * Handle when the Video has been Initialized
322
- */
323
- _onVideoInitialized() {
324
- this._eventEmitter.dispatchEvent(new VideoInitializedEvent());
325
- this._videoStartTime = Date.now();
326
- }
327
- /**
328
- * Set up functionality to happen when receiving latency test results
329
- * @param latency - latency test results object
330
- */
331
- _onLatencyTestResult(latencyTimings) {
332
- this._eventEmitter.dispatchEvent(new LatencyTestResultEvent({ latencyTimings }));
333
- }
334
- _onDataChannelLatencyTestResponse(response) {
335
- this._eventEmitter.dispatchEvent(new DataChannelLatencyTestResponseEvent({ response }));
336
- }
337
- /**
338
- * Set up functionality to happen when receiving video statistics
339
- * @param videoStats - video statistics as a aggregate stats object
340
- */
341
- _onVideoStats(videoStats) {
342
- // Duration
343
- if (!this._videoStartTime || this._videoStartTime === undefined) {
344
- this._videoStartTime = Date.now();
345
- }
346
- videoStats.handleSessionStatistics(this._videoStartTime, this._inputController, this._webRtcController.videoAvgQp);
347
- this._eventEmitter.dispatchEvent(new StatsReceivedEvent({ aggregatedStats: videoStats }));
348
- }
349
- /**
350
- * Set up functionality to happen when calculating the average video encoder qp
351
- * @param QP - the quality number of the stream
352
- */
353
- _onVideoEncoderAvgQP(QP) {
354
- this._eventEmitter.dispatchEvent(new VideoEncoderAvgQPEvent({ avgQP: QP }));
355
- }
356
- /**
357
- * Set up functionality to happen when receiving and handling initial settings for the UE app
358
- * @param settings - initial UE app settings
359
- */
360
- _onInitialSettings(settings) {
361
- var _a;
362
- this._eventEmitter.dispatchEvent(new InitialSettingsEvent({ settings }));
363
- if (settings.PixelStreamingSettings) {
364
- this.allowConsoleCommands = (_a = settings.PixelStreamingSettings.AllowPixelStreamingCommands) !== null && _a !== void 0 ? _a : false;
365
- if (this.allowConsoleCommands === false) {
366
- Logger.Info('-AllowPixelStreamingCommands=false, sending arbitrary console commands from browser to UE is disabled.');
367
- }
368
- }
369
- const useUrlParams = this.config.useUrlParams;
370
- const urlParams = new IURLSearchParams(window.location.search);
371
- Logger.Info(`using URL parameters ${useUrlParams}`);
372
- if (settings.EncoderSettings) {
373
- this.config.setNumericSetting(NumericParameters.MinQP,
374
- // If a setting is set in the URL, make sure we respect that value as opposed to what the application sends us
375
- useUrlParams && urlParams.has(NumericParameters.MinQP)
376
- ? Number.parseFloat(urlParams.get(NumericParameters.MinQP))
377
- : settings.EncoderSettings.MinQP);
378
- this.config.setNumericSetting(NumericParameters.MaxQP, useUrlParams && urlParams.has(NumericParameters.MaxQP)
379
- ? Number.parseFloat(urlParams.get(NumericParameters.MaxQP))
380
- : settings.EncoderSettings.MaxQP);
381
- }
382
- if (settings.WebRTCSettings) {
383
- this.config.setNumericSetting(NumericParameters.WebRTCMinBitrate, useUrlParams && urlParams.has(NumericParameters.WebRTCMinBitrate)
384
- ? Number.parseFloat(urlParams.get(NumericParameters.WebRTCMinBitrate))
385
- : settings.WebRTCSettings.MinBitrate / 1000 /* bps to kbps */);
386
- this.config.setNumericSetting(NumericParameters.WebRTCMaxBitrate, useUrlParams && urlParams.has(NumericParameters.WebRTCMaxBitrate)
387
- ? Number.parseFloat(urlParams.get(NumericParameters.WebRTCMaxBitrate))
388
- : settings.WebRTCSettings.MaxBitrate / 1000 /* bps to kbps */);
389
- this.config.setNumericSetting(NumericParameters.WebRTCFPS, useUrlParams && urlParams.has(NumericParameters.WebRTCFPS)
390
- ? Number.parseFloat(urlParams.get(NumericParameters.WebRTCFPS))
391
- : settings.WebRTCSettings.FPS);
392
- }
393
- }
394
- /**
395
- * Set up functionality to happen when setting quality control ownership of a stream
396
- * @param hasQualityOwnership - does this user have quality ownership of the stream true / false
397
- */
398
- _onQualityControlOwnership(hasQualityOwnership) {
399
- this.config.setFlagEnabled(Flags.IsQualityController, hasQualityOwnership);
400
- }
401
- _onPlayerCount(playerCount) {
402
- this._eventEmitter.dispatchEvent(new PlayerCountEvent({ count: playerCount }));
403
- }
404
- // Sets up to emit the webrtc tcp relay detect event
405
- _setupWebRtcTCPRelayDetection(statsReceivedEvent) {
406
- // Get the active candidate pair
407
- const activeCandidatePair = statsReceivedEvent.data.aggregatedStats.getActiveCandidatePair();
408
- // Check if the active candidate pair is not null
409
- if (activeCandidatePair != null) {
410
- // Get the local candidate assigned to the active candidate pair
411
- const localCandidate = statsReceivedEvent.data.aggregatedStats.localCandidates.find((candidate) => candidate.id == activeCandidatePair.localCandidateId, null);
412
- // Check if the local candidate is not null, candidate type is relay and the relay protocol is tcp
413
- if (localCandidate != null &&
414
- localCandidate.candidateType == 'relay' &&
415
- localCandidate.relayProtocol == 'tcp') {
416
- // Send the web rtc tcp relay detected event
417
- this._eventEmitter.dispatchEvent(new WebRtcTCPRelayDetectedEvent());
418
- }
419
- // The check is completed and the stats listen event can be removed
420
- this._eventEmitter.removeEventListener('statsReceived', this._setupWebRtcTCPRelayDetection);
421
- }
422
- }
423
- /**
424
- * Request a connection latency test.
425
- * NOTE: There are plans to refactor all request* functions. Expect changes if you use this!
426
- * @returns
427
- */
428
- requestLatencyTest() {
429
- if (!this._webRtcController.videoPlayer.isVideoReady()) {
430
- return false;
431
- }
432
- this._webRtcController.sendLatencyTest();
433
- return true;
434
- }
435
- /**
436
- * Request a data channel latency test.
437
- * NOTE: There are plans to refactor all request* functions. Expect changes if you use this!
438
- */
439
- requestDataChannelLatencyTest(config) {
440
- if (!this._webRtcController.videoPlayer.isVideoReady()) {
441
- return false;
442
- }
443
- if (!this._dataChannelLatencyTestController) {
444
- this._dataChannelLatencyTestController = new DataChannelLatencyTestController(this._webRtcController.sendDataChannelLatencyTest.bind(this._webRtcController), (result) => {
445
- this._eventEmitter.dispatchEvent(new DataChannelLatencyTestResultEvent({ result }));
446
- });
447
- this.addEventListener('dataChannelLatencyTestResponse', ({ data: { response } }) => {
448
- this._dataChannelLatencyTestController.receive(response);
449
- });
450
- }
451
- return this._dataChannelLatencyTestController.start(config);
452
- }
453
- /**
454
- * Request for the UE application to show FPS counter.
455
- * NOTE: There are plans to refactor all request* functions. Expect changes if you use this!
456
- * @returns
457
- */
458
- requestShowFps() {
459
- if (!this._webRtcController.videoPlayer.isVideoReady()) {
460
- return false;
461
- }
462
- this._webRtcController.sendShowFps();
463
- return true;
464
- }
465
- /**
466
- * Request for a new IFrame from the UE application.
467
- * NOTE: There are plans to refactor all request* functions. Expect changes if you use this!
468
- * @returns
469
- */
470
- requestIframe() {
471
- if (!this._webRtcController.videoPlayer.isVideoReady()) {
472
- return false;
473
- }
474
- this._webRtcController.sendIframeRequest();
475
- return true;
476
- }
477
- /**
478
- * Send data to UE application. The data will be run through JSON.stringify() so e.g. strings
479
- * and any serializable plain JSON objects with no recurrence can be sent.
480
- * @returns true if succeeded, false if rejected
481
- */
482
- emitUIInteraction(descriptor) {
483
- if (!this._webRtcController.videoPlayer.isVideoReady()) {
484
- return false;
485
- }
486
- this._webRtcController.emitUIInteraction(descriptor);
487
- return true;
488
- }
489
- /**
490
- * Send a command to UE application. Blocks ConsoleCommand descriptors unless UE
491
- * has signaled that it allows console commands.
492
- * @returns true if succeeded, false if rejected
493
- */
494
- emitCommand(descriptor) {
495
- if (!this._webRtcController.videoPlayer.isVideoReady()) {
496
- return false;
497
- }
498
- if (!this.allowConsoleCommands && 'ConsoleCommand' in descriptor) {
499
- return false;
500
- }
501
- this._webRtcController.emitCommand(descriptor);
502
- return true;
503
- }
504
- /**
505
- * Send a console command to UE application. Only allowed if UE has signaled that it allows
506
- * console commands.
507
- * @returns true if succeeded, false if rejected
508
- */
509
- emitConsoleCommand(command) {
510
- if (!this.allowConsoleCommands || !this._webRtcController.videoPlayer.isVideoReady()) {
511
- return false;
512
- }
513
- this._webRtcController.emitConsoleCommand(command);
514
- return true;
515
- }
516
- /**
517
- * Add a UE -> browser response event listener
518
- * @param name - The name of the response handler
519
- * @param listener - The method to be activated when a message is received
520
- */
521
- addResponseEventListener(name, listener) {
522
- this._webRtcController.responseController.addResponseEventListener(name, listener);
523
- }
524
- /**
525
- * Remove a UE -> browser response event listener
526
- * @param name - The name of the response handler
527
- */
528
- removeResponseEventListener(name) {
529
- this._webRtcController.responseController.removeResponseEventListener(name);
530
- }
531
- /**
532
- * Dispatch a new event.
533
- * @param e event
534
- * @returns
535
- */
536
- dispatchEvent(e) {
537
- return this._eventEmitter.dispatchEvent(e);
538
- }
539
- /**
540
- * Register an event handler.
541
- * @param type event name
542
- * @param listener event handler function
543
- */
544
- addEventListener(type, listener) {
545
- this._eventEmitter.addEventListener(type, listener);
546
- }
547
- /**
548
- * Remove an event handler.
549
- * @param type event name
550
- * @param listener event handler function
551
- */
552
- removeEventListener(type, listener) {
553
- this._eventEmitter.removeEventListener(type, listener);
554
- }
555
- /**
556
- * Enable/disable XR mode.
557
- */
558
- toggleXR() {
559
- this.webXrController.xrClicked();
560
- }
561
- /**
562
- * Pass in a function to generate a signalling server URL.
563
- * This function is useful if you need to programmatically construct your signalling server URL.
564
- * @param signallingUrlBuilderFunc A function that generates a signalling server url.
565
- */
566
- setSignallingUrlBuilder(signallingUrlBuilderFunc) {
567
- this._webRtcController.signallingUrlBuilder = signallingUrlBuilderFunc;
568
- }
569
- get webRtcController() {
570
- return this._webRtcController;
571
- }
572
- /**
573
- * Public getter for the websocket controller. Access to this property allows you to send
574
- * custom websocket messages.
575
- */
576
- get signallingProtocol() {
577
- return this._webRtcController.protocol;
578
- }
579
- /**
580
- * Public getter for the webXrController controller. Used for all XR features.
581
- */
582
- get webXrController() {
583
- return this._webXrController;
584
- }
585
- registerMessageHandler(name, direction, handler) {
586
- if (direction === MessageDirection.FromStreamer && typeof handler === 'undefined') {
587
- Logger.Warning(`Unable to register an undefined handler for ${name}`);
588
- return;
589
- }
590
- if (direction === MessageDirection.ToStreamer && typeof handler === 'undefined') {
591
- this._webRtcController.streamMessageController.registerMessageHandler(direction, name, (data) => this._webRtcController.sendMessageController.sendMessageToStreamer(name, data));
592
- }
593
- else {
594
- this._webRtcController.streamMessageController.registerMessageHandler(direction, name, (data) => handler(data));
595
- }
596
- }
597
- get toStreamerHandlers() {
598
- return this._webRtcController.streamMessageController.toStreamerHandlers;
599
- }
600
- isReconnecting() {
601
- return this._webRtcController.isReconnecting;
602
- }
603
- }
1
+ // Copyright Epic Games, Inc. All Rights Reserved.
2
+ import { OptionParameters } from '../Config/Config';
3
+ import { WebRtcPlayerController } from '../WebRtcPlayer/WebRtcPlayerController';
4
+ import { Flags, NumericParameters } from '../Config/Config';
5
+ import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
6
+ import { OnScreenKeyboard } from '../UI/OnScreenKeyboard';
7
+ import { EventEmitter, InitialSettingsEvent, LatencyTestResultEvent, StatsReceivedEvent, StreamLoadingEvent, StreamPreConnectEvent, StreamReconnectEvent, StreamPreDisconnectEvent, VideoEncoderAvgQPEvent, VideoInitializedEvent, WebRtcAutoConnectEvent, WebRtcConnectedEvent, WebRtcConnectingEvent, WebRtcDisconnectedEvent, WebRtcFailedEvent, WebRtcSdpEvent, DataChannelLatencyTestResponseEvent, DataChannelLatencyTestResultEvent, PlayerCountEvent, WebRtcTCPRelayDetectedEvent } from '../Util/EventEmitter';
8
+ import { WebXRController } from '../WebXR/WebXRController';
9
+ import { MessageDirection } from '../UeInstanceMessage/StreamMessageController';
10
+ import { DataChannelLatencyTestController } from '../DataChannel/DataChannelLatencyTestController';
11
+ import { RTCUtils } from '../Util/RTCUtils';
12
+ import { IURLSearchParams } from '../Util/IURLSearchParams';
13
+ /**
14
+ * The key class for the browser side of a Pixel Streaming application, it includes:
15
+ * WebRTC handling, XR support, input handling, and emitters for lifetime and state change events.
16
+ * Users are encouraged to use this class as is, through composition, or extend it. In any case,
17
+ * this will likely be the core of your Pixel Streaming experience in terms of functionality.
18
+ */
19
+ export class PixelStreaming {
20
+ /**
21
+ * @param config - A newly instantiated config object
22
+ * @param overrides - Parameters to override default behaviour
23
+ * returns the base Pixel streaming object
24
+ */
25
+ constructor(config, overrides) {
26
+ this.allowConsoleCommands = false;
27
+ this.config = config;
28
+ if (overrides === null || overrides === void 0 ? void 0 : overrides.videoElementParent) {
29
+ this._videoElementParent = overrides.videoElementParent;
30
+ }
31
+ this._eventEmitter = new EventEmitter();
32
+ this.configureSettings();
33
+ // setup WebRTC
34
+ this.setWebRtcPlayerController(new WebRtcPlayerController(this.config, this));
35
+ // Onscreen keyboard
36
+ this.onScreenKeyboardHelper = new OnScreenKeyboard(this.videoElementParent);
37
+ this.onScreenKeyboardHelper.unquantizeAndDenormalizeUnsigned = (x, y) => this._webRtcController.requestUnquantizedAndDenormalizeUnsigned(x, y);
38
+ this._activateOnScreenKeyboard = (command) => this.onScreenKeyboardHelper.showOnScreenKeyboard(command);
39
+ this._webXrController = new WebXRController(this._webRtcController);
40
+ this._setupWebRtcTCPRelayDetection = this._setupWebRtcTCPRelayDetection.bind(this);
41
+ // Add event listener for the webRtcConnected event
42
+ this._eventEmitter.addEventListener('webRtcConnected', (_) => {
43
+ // Bind to the stats received event
44
+ this._eventEmitter.addEventListener('statsReceived', this._setupWebRtcTCPRelayDetection);
45
+ });
46
+ }
47
+ /**
48
+ * Gets the element that contains the video stream element.
49
+ */
50
+ get videoElementParent() {
51
+ if (!this._videoElementParent) {
52
+ this._videoElementParent = document.createElement('div');
53
+ this._videoElementParent.id = 'videoElementParent';
54
+ }
55
+ return this._videoElementParent;
56
+ }
57
+ /**
58
+ * Configure the settings with on change listeners and any additional per experience settings.
59
+ */
60
+ configureSettings() {
61
+ this.config._addOnSettingChangedListener(Flags.IsQualityController, (wantsQualityController) => {
62
+ // If the setting has been set to true (either programmatically or the user has flicked the toggle)
63
+ // and we aren't currently quality controller, send the request
64
+ if (wantsQualityController === true && !this._webRtcController.isQualityController) {
65
+ this._webRtcController.sendRequestQualityControlOwnership();
66
+ }
67
+ });
68
+ this.config._addOnSettingChangedListener(Flags.AFKDetection, (isAFKEnabled) => {
69
+ this._webRtcController.setAfkEnabled(isAFKEnabled);
70
+ });
71
+ this.config._addOnSettingChangedListener(Flags.MatchViewportResolution, () => {
72
+ this._webRtcController.videoPlayer.updateVideoStreamSize();
73
+ });
74
+ this.config._addOnSettingChangedListener(Flags.HoveringMouseMode, (isHoveringMouse) => {
75
+ this.config.setFlagLabel(Flags.HoveringMouseMode, `Control Scheme: ${isHoveringMouse ? 'Hovering' : 'Locked'} Mouse`);
76
+ this._webRtcController.setMouseInputEnabled(this.config.isFlagEnabled(Flags.MouseInput));
77
+ });
78
+ // user input
79
+ this.config._addOnSettingChangedListener(Flags.KeyboardInput, (isEnabled) => {
80
+ this._webRtcController.setKeyboardInputEnabled(isEnabled);
81
+ });
82
+ this.config._addOnSettingChangedListener(Flags.MouseInput, (isEnabled) => {
83
+ this._webRtcController.setMouseInputEnabled(isEnabled);
84
+ });
85
+ this.config._addOnSettingChangedListener(Flags.FakeMouseWithTouches, (_isFakeMouseEnabled) => {
86
+ this._webRtcController.setTouchInputEnabled(this.config.isFlagEnabled(Flags.TouchInput));
87
+ });
88
+ this.config._addOnSettingChangedListener(Flags.TouchInput, (isEnabled) => {
89
+ this._webRtcController.setTouchInputEnabled(isEnabled);
90
+ });
91
+ this.config._addOnSettingChangedListener(Flags.GamepadInput, (isEnabled) => {
92
+ this._webRtcController.setGamePadInputEnabled(isEnabled);
93
+ });
94
+ // encoder settings
95
+ this.config._addOnNumericSettingChangedListener(NumericParameters.MinQP, (newValue) => {
96
+ Logger.Info('-------- Sending MinQP --------');
97
+ this._webRtcController.sendEncoderMinQP(newValue);
98
+ Logger.Info('-------------------------------------------');
99
+ });
100
+ this.config._addOnNumericSettingChangedListener(NumericParameters.MaxQP, (newValue) => {
101
+ Logger.Info('-------- Sending encoder settings --------');
102
+ this._webRtcController.sendEncoderMaxQP(newValue);
103
+ Logger.Info('-------------------------------------------');
104
+ });
105
+ // WebRTC settings
106
+ this.config._addOnNumericSettingChangedListener(NumericParameters.WebRTCMinBitrate, (newValue) => {
107
+ Logger.Info('-------- Sending web rtc settings --------');
108
+ this._webRtcController.sendWebRTCMinBitrate(newValue * 1000 /* kbps to bps */);
109
+ Logger.Info('-------------------------------------------');
110
+ });
111
+ this.config._addOnNumericSettingChangedListener(NumericParameters.WebRTCMaxBitrate, (newValue) => {
112
+ Logger.Info('-------- Sending web rtc settings --------');
113
+ this._webRtcController.sendWebRTCMaxBitrate(newValue * 1000 /* kbps to bps */);
114
+ Logger.Info('-------------------------------------------');
115
+ });
116
+ this.config._addOnNumericSettingChangedListener(NumericParameters.WebRTCFPS, (newValue) => {
117
+ Logger.Info('-------- Sending web rtc settings --------');
118
+ this._webRtcController.sendWebRTCFps(newValue);
119
+ Logger.Info('-------------------------------------------');
120
+ });
121
+ this.config._addOnOptionSettingChangedListener(OptionParameters.PreferredCodec, (newValue) => {
122
+ if (this._webRtcController) {
123
+ this._webRtcController.setPreferredCodec(newValue);
124
+ }
125
+ });
126
+ this.config._registerOnChangeEvents(this._eventEmitter);
127
+ }
128
+ /**
129
+ * Activate the on screen keyboard when receiving the command from the streamer
130
+ * @param command - the keyboard command
131
+ */
132
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
133
+ _activateOnScreenKeyboard(command) {
134
+ throw new Error('Method not implemented.');
135
+ }
136
+ /**
137
+ * Set the input control ownership
138
+ * @param inputControlOwnership - does the user have input control ownership
139
+ */
140
+ _onInputControlOwnership(inputControlOwnership) {
141
+ this._inputController = inputControlOwnership;
142
+ }
143
+ /**
144
+ * Instantiate the WebRTCPlayerController interface to provide WebRTCPlayerController functionality within this class and set up anything that requires it
145
+ * @param webRtcPlayerController - a WebRtcPlayerController controller instance
146
+ */
147
+ setWebRtcPlayerController(webRtcPlayerController) {
148
+ this._webRtcController = webRtcPlayerController;
149
+ this._webRtcController.setPreferredCodec(this.config.getSettingOption(OptionParameters.PreferredCodec).selected);
150
+ this._webRtcController.resizePlayerStyle();
151
+ // connect if auto connect flag is enabled
152
+ this.checkForAutoConnect();
153
+ }
154
+ /**
155
+ * Connect to signaling server.
156
+ */
157
+ connect() {
158
+ this._eventEmitter.dispatchEvent(new StreamPreConnectEvent());
159
+ this._webRtcController.connectToSignallingServer();
160
+ }
161
+ /**
162
+ * Reconnects to the signaling server. If connection is up, disconnects first
163
+ * before establishing a new connection
164
+ */
165
+ reconnect() {
166
+ this._eventEmitter.dispatchEvent(new StreamReconnectEvent());
167
+ this._webRtcController.tryReconnect('Reconnecting...');
168
+ }
169
+ /**
170
+ * Disconnect from the signaling server and close open peer connections.
171
+ */
172
+ disconnect() {
173
+ this._eventEmitter.dispatchEvent(new StreamPreDisconnectEvent());
174
+ this._webRtcController.close();
175
+ }
176
+ /**
177
+ * Play the stream. Can be called only after a peer connection has been established.
178
+ */
179
+ play() {
180
+ this._onStreamLoading();
181
+ this._webRtcController.playStream();
182
+ }
183
+ /**
184
+ * Auto connect if AutoConnect flag is enabled
185
+ */
186
+ checkForAutoConnect() {
187
+ // set up if the auto play will be used or regular click to start
188
+ if (this.config.isFlagEnabled(Flags.AutoConnect)) {
189
+ // if autoplaying show an info overlay while while waiting for the connection to begin
190
+ this._onWebRtcAutoConnect();
191
+ this._webRtcController.connectToSignallingServer();
192
+ }
193
+ }
194
+ /**
195
+ * Will unmute the microphone track which is sent to Unreal Engine.
196
+ * By default, will only unmute an existing mic track.
197
+ *
198
+ * @param forceEnable Can be used for cases when this object wasn't initialized with a mic track.
199
+ * If this parameter is true, the connection will be restarted with a microphone.
200
+ * Warning: this takes some time, as a full renegotiation and reconnection will happen.
201
+ */
202
+ unmuteMicrophone(forceEnable = false) {
203
+ // If there's an existing mic track, we just set muted state
204
+ if (this.config.isFlagEnabled('UseMic')) {
205
+ this.setMicrophoneMuted(false);
206
+ return;
207
+ }
208
+ // If there's no pre-existing mic track, and caller is ok with full reset, we enable and reset
209
+ if (forceEnable) {
210
+ this.config.setFlagEnabled('UseMic', true);
211
+ this.reconnect();
212
+ return;
213
+ }
214
+ // If we prefer not to force a reconnection, just warn the user that this operation didn't happen
215
+ Logger.Warning('Trying to unmute mic, but PixelStreaming was initialized with no microphone track. Call with forceEnable == true to re-connect with a mic track.');
216
+ }
217
+ muteMicrophone() {
218
+ if (this.config.isFlagEnabled('UseMic')) {
219
+ this.setMicrophoneMuted(true);
220
+ return;
221
+ }
222
+ // If there wasn't a mic track, just let user know there's nothing to mute
223
+ Logger.Info('Trying to mute mic, but PixelStreaming has no microphone track, so sending sound is already disabled.');
224
+ }
225
+ setMicrophoneMuted(mute) {
226
+ var _a, _b, _c, _d;
227
+ for (const transceiver of (_d = (_c = (_b = (_a = this._webRtcController) === null || _a === void 0 ? void 0 : _a.peerConnectionController) === null || _b === void 0 ? void 0 : _b.peerConnection) === null || _c === void 0 ? void 0 : _c.getTransceivers()) !== null && _d !== void 0 ? _d : []) {
228
+ if (RTCUtils.canTransceiverSendAudio(transceiver)) {
229
+ transceiver.sender.track.enabled = !mute;
230
+ }
231
+ }
232
+ }
233
+ /**
234
+ * Will unmute the video track which is sent to Unreal Engine.
235
+ * By default, will only unmute an existing video track.
236
+ *
237
+ * @param forceEnable Can be used for cases when this object wasn't initialized with a video track.
238
+ * If this parameter is true, the connection will be restarted with a camera.
239
+ * Warning: this takes some time, as a full renegotiation and reconnection will happen.
240
+ */
241
+ unmuteCamera(forceEnable = false) {
242
+ // If there's an existing video track, we just set muted state
243
+ if (this.config.isFlagEnabled('UseCamera')) {
244
+ this.setCameraMuted(false);
245
+ return;
246
+ }
247
+ // If there's no pre-existing video track, and caller is ok with full reset, we enable and reset
248
+ if (forceEnable) {
249
+ this.config.setFlagEnabled('UseCamera', true);
250
+ this.reconnect();
251
+ return;
252
+ }
253
+ // If we prefer not to force a reconnection, just warn the user that this operation didn't happen
254
+ Logger.Warning('Trying to unmute video, but PixelStreaming was initialized with no video track. Call with forceEnable == true to re-connect with a video track.');
255
+ }
256
+ muteCamera() {
257
+ if (this.config.isFlagEnabled('UseCamera')) {
258
+ this.setCameraMuted(true);
259
+ return;
260
+ }
261
+ // If there wasn't a mic track, just let user know there's nothing to mute
262
+ Logger.Info('Trying to mute camera, but PixelStreaming has no video track, so sending video is already disabled.');
263
+ }
264
+ setCameraMuted(mute) {
265
+ var _a, _b, _c, _d;
266
+ for (const transceiver of (_d = (_c = (_b = (_a = this._webRtcController) === null || _a === void 0 ? void 0 : _a.peerConnectionController) === null || _b === void 0 ? void 0 : _b.peerConnection) === null || _c === void 0 ? void 0 : _c.getTransceivers()) !== null && _d !== void 0 ? _d : []) {
267
+ if (RTCUtils.canTransceiverSendVideo(transceiver)) {
268
+ transceiver.sender.track.enabled = !mute;
269
+ }
270
+ }
271
+ }
272
+ /**
273
+ * Emit an event on auto connecting
274
+ */
275
+ _onWebRtcAutoConnect() {
276
+ this._eventEmitter.dispatchEvent(new WebRtcAutoConnectEvent());
277
+ }
278
+ /**
279
+ * Set up functionality to happen when receiving a webRTC answer
280
+ */
281
+ _onWebRtcSdp() {
282
+ this._eventEmitter.dispatchEvent(new WebRtcSdpEvent());
283
+ }
284
+ /**
285
+ * Emits a StreamLoading event
286
+ */
287
+ _onStreamLoading() {
288
+ this._eventEmitter.dispatchEvent(new StreamLoadingEvent());
289
+ }
290
+ /**
291
+ * Event fired when the video is disconnected - emits given eventString or an override
292
+ * message from webRtcController if one has been set
293
+ * @param eventString - a string describing why the connection closed
294
+ * @param allowClickToReconnect - true if we want to allow the user to retry the connection with a click
295
+ */
296
+ _onDisconnect(eventString, allowClickToReconnect) {
297
+ this._eventEmitter.dispatchEvent(new WebRtcDisconnectedEvent({
298
+ eventString: eventString,
299
+ allowClickToReconnect: allowClickToReconnect
300
+ }));
301
+ }
302
+ /**
303
+ * Handles when Web Rtc is connecting
304
+ */
305
+ _onWebRtcConnecting() {
306
+ this._eventEmitter.dispatchEvent(new WebRtcConnectingEvent());
307
+ }
308
+ /**
309
+ * Handles when Web Rtc has connected
310
+ */
311
+ _onWebRtcConnected() {
312
+ this._eventEmitter.dispatchEvent(new WebRtcConnectedEvent());
313
+ }
314
+ /**
315
+ * Handles when Web Rtc fails to connect
316
+ */
317
+ _onWebRtcFailed() {
318
+ this._eventEmitter.dispatchEvent(new WebRtcFailedEvent());
319
+ }
320
+ /**
321
+ * Handle when the Video has been Initialized
322
+ */
323
+ _onVideoInitialized() {
324
+ this._eventEmitter.dispatchEvent(new VideoInitializedEvent());
325
+ this._videoStartTime = Date.now();
326
+ }
327
+ /**
328
+ * Set up functionality to happen when receiving latency test results
329
+ * @param latency - latency test results object
330
+ */
331
+ _onLatencyTestResult(latencyTimings) {
332
+ this._eventEmitter.dispatchEvent(new LatencyTestResultEvent({ latencyTimings }));
333
+ }
334
+ _onDataChannelLatencyTestResponse(response) {
335
+ this._eventEmitter.dispatchEvent(new DataChannelLatencyTestResponseEvent({ response }));
336
+ }
337
+ /**
338
+ * Set up functionality to happen when receiving video statistics
339
+ * @param videoStats - video statistics as a aggregate stats object
340
+ */
341
+ _onVideoStats(videoStats) {
342
+ // Duration
343
+ if (!this._videoStartTime || this._videoStartTime === undefined) {
344
+ this._videoStartTime = Date.now();
345
+ }
346
+ videoStats.handleSessionStatistics(this._videoStartTime, this._inputController, this._webRtcController.videoAvgQp);
347
+ this._eventEmitter.dispatchEvent(new StatsReceivedEvent({ aggregatedStats: videoStats }));
348
+ }
349
+ /**
350
+ * Set up functionality to happen when calculating the average video encoder qp
351
+ * @param QP - the quality number of the stream
352
+ */
353
+ _onVideoEncoderAvgQP(QP) {
354
+ this._eventEmitter.dispatchEvent(new VideoEncoderAvgQPEvent({ avgQP: QP }));
355
+ }
356
+ /**
357
+ * Set up functionality to happen when receiving and handling initial settings for the UE app
358
+ * @param settings - initial UE app settings
359
+ */
360
+ _onInitialSettings(settings) {
361
+ var _a;
362
+ this._eventEmitter.dispatchEvent(new InitialSettingsEvent({ settings }));
363
+ if (settings.PixelStreamingSettings) {
364
+ this.allowConsoleCommands = (_a = settings.PixelStreamingSettings.AllowPixelStreamingCommands) !== null && _a !== void 0 ? _a : false;
365
+ if (this.allowConsoleCommands === false) {
366
+ Logger.Info('-AllowPixelStreamingCommands=false, sending arbitrary console commands from browser to UE is disabled.');
367
+ }
368
+ }
369
+ const useUrlParams = this.config.useUrlParams;
370
+ const urlParams = new IURLSearchParams(window.location.search);
371
+ Logger.Info(`using URL parameters ${useUrlParams}`);
372
+ if (settings.EncoderSettings) {
373
+ this.config.setNumericSetting(NumericParameters.MinQP,
374
+ // If a setting is set in the URL, make sure we respect that value as opposed to what the application sends us
375
+ useUrlParams && urlParams.has(NumericParameters.MinQP)
376
+ ? Number.parseFloat(urlParams.get(NumericParameters.MinQP))
377
+ : settings.EncoderSettings.MinQP);
378
+ this.config.setNumericSetting(NumericParameters.MaxQP, useUrlParams && urlParams.has(NumericParameters.MaxQP)
379
+ ? Number.parseFloat(urlParams.get(NumericParameters.MaxQP))
380
+ : settings.EncoderSettings.MaxQP);
381
+ }
382
+ if (settings.WebRTCSettings) {
383
+ this.config.setNumericSetting(NumericParameters.WebRTCMinBitrate, useUrlParams && urlParams.has(NumericParameters.WebRTCMinBitrate)
384
+ ? Number.parseFloat(urlParams.get(NumericParameters.WebRTCMinBitrate))
385
+ : settings.WebRTCSettings.MinBitrate / 1000 /* bps to kbps */);
386
+ this.config.setNumericSetting(NumericParameters.WebRTCMaxBitrate, useUrlParams && urlParams.has(NumericParameters.WebRTCMaxBitrate)
387
+ ? Number.parseFloat(urlParams.get(NumericParameters.WebRTCMaxBitrate))
388
+ : settings.WebRTCSettings.MaxBitrate / 1000 /* bps to kbps */);
389
+ this.config.setNumericSetting(NumericParameters.WebRTCFPS, useUrlParams && urlParams.has(NumericParameters.WebRTCFPS)
390
+ ? Number.parseFloat(urlParams.get(NumericParameters.WebRTCFPS))
391
+ : settings.WebRTCSettings.FPS);
392
+ }
393
+ }
394
+ /**
395
+ * Set up functionality to happen when setting quality control ownership of a stream
396
+ * @param hasQualityOwnership - does this user have quality ownership of the stream true / false
397
+ */
398
+ _onQualityControlOwnership(hasQualityOwnership) {
399
+ this.config.setFlagEnabled(Flags.IsQualityController, hasQualityOwnership);
400
+ }
401
+ _onPlayerCount(playerCount) {
402
+ this._eventEmitter.dispatchEvent(new PlayerCountEvent({ count: playerCount }));
403
+ }
404
+ // Sets up to emit the webrtc tcp relay detect event
405
+ _setupWebRtcTCPRelayDetection(statsReceivedEvent) {
406
+ // Get the active candidate pair
407
+ const activeCandidatePair = statsReceivedEvent.data.aggregatedStats.getActiveCandidatePair();
408
+ // Check if the active candidate pair is not null
409
+ if (activeCandidatePair != null) {
410
+ // Get the local candidate assigned to the active candidate pair
411
+ const localCandidate = statsReceivedEvent.data.aggregatedStats.localCandidates.find((candidate) => candidate.id == activeCandidatePair.localCandidateId, null);
412
+ // Check if the local candidate is not null, candidate type is relay and the relay protocol is tcp
413
+ if (localCandidate != null &&
414
+ localCandidate.candidateType == 'relay' &&
415
+ localCandidate.relayProtocol == 'tcp') {
416
+ // Send the web rtc tcp relay detected event
417
+ this._eventEmitter.dispatchEvent(new WebRtcTCPRelayDetectedEvent());
418
+ }
419
+ // The check is completed and the stats listen event can be removed
420
+ this._eventEmitter.removeEventListener('statsReceived', this._setupWebRtcTCPRelayDetection);
421
+ }
422
+ }
423
+ /**
424
+ * Request a connection latency test.
425
+ * NOTE: There are plans to refactor all request* functions. Expect changes if you use this!
426
+ * @returns
427
+ */
428
+ requestLatencyTest() {
429
+ if (!this._webRtcController.videoPlayer.isVideoReady()) {
430
+ return false;
431
+ }
432
+ this._webRtcController.sendLatencyTest();
433
+ return true;
434
+ }
435
+ /**
436
+ * Request a data channel latency test.
437
+ * NOTE: There are plans to refactor all request* functions. Expect changes if you use this!
438
+ */
439
+ requestDataChannelLatencyTest(config) {
440
+ if (!this._webRtcController.videoPlayer.isVideoReady()) {
441
+ return false;
442
+ }
443
+ if (!this._dataChannelLatencyTestController) {
444
+ this._dataChannelLatencyTestController = new DataChannelLatencyTestController(this._webRtcController.sendDataChannelLatencyTest.bind(this._webRtcController), (result) => {
445
+ this._eventEmitter.dispatchEvent(new DataChannelLatencyTestResultEvent({ result }));
446
+ });
447
+ this.addEventListener('dataChannelLatencyTestResponse', ({ data: { response } }) => {
448
+ this._dataChannelLatencyTestController.receive(response);
449
+ });
450
+ }
451
+ return this._dataChannelLatencyTestController.start(config);
452
+ }
453
+ /**
454
+ * Request for the UE application to show FPS counter.
455
+ * NOTE: There are plans to refactor all request* functions. Expect changes if you use this!
456
+ * @returns
457
+ */
458
+ requestShowFps() {
459
+ if (!this._webRtcController.videoPlayer.isVideoReady()) {
460
+ return false;
461
+ }
462
+ this._webRtcController.sendShowFps();
463
+ return true;
464
+ }
465
+ /**
466
+ * Request for a new IFrame from the UE application.
467
+ * NOTE: There are plans to refactor all request* functions. Expect changes if you use this!
468
+ * @returns
469
+ */
470
+ requestIframe() {
471
+ if (!this._webRtcController.videoPlayer.isVideoReady()) {
472
+ return false;
473
+ }
474
+ this._webRtcController.sendIframeRequest();
475
+ return true;
476
+ }
477
+ /**
478
+ * Send data to UE application. The data will be run through JSON.stringify() so e.g. strings
479
+ * and any serializable plain JSON objects with no recurrence can be sent.
480
+ * @returns true if succeeded, false if rejected
481
+ */
482
+ emitUIInteraction(descriptor) {
483
+ if (!this._webRtcController.videoPlayer.isVideoReady()) {
484
+ return false;
485
+ }
486
+ this._webRtcController.emitUIInteraction(descriptor);
487
+ return true;
488
+ }
489
+ /**
490
+ * Send a command to UE application. Blocks ConsoleCommand descriptors unless UE
491
+ * has signaled that it allows console commands.
492
+ * @returns true if succeeded, false if rejected
493
+ */
494
+ emitCommand(descriptor) {
495
+ if (!this._webRtcController.videoPlayer.isVideoReady()) {
496
+ return false;
497
+ }
498
+ if (!this.allowConsoleCommands && 'ConsoleCommand' in descriptor) {
499
+ return false;
500
+ }
501
+ this._webRtcController.emitCommand(descriptor);
502
+ return true;
503
+ }
504
+ /**
505
+ * Send a console command to UE application. Only allowed if UE has signaled that it allows
506
+ * console commands.
507
+ * @returns true if succeeded, false if rejected
508
+ */
509
+ emitConsoleCommand(command) {
510
+ if (!this.allowConsoleCommands || !this._webRtcController.videoPlayer.isVideoReady()) {
511
+ return false;
512
+ }
513
+ this._webRtcController.emitConsoleCommand(command);
514
+ return true;
515
+ }
516
+ /**
517
+ * Add a UE -> browser response event listener
518
+ * @param name - The name of the response handler
519
+ * @param listener - The method to be activated when a message is received
520
+ */
521
+ addResponseEventListener(name, listener) {
522
+ this._webRtcController.responseController.addResponseEventListener(name, listener);
523
+ }
524
+ /**
525
+ * Remove a UE -> browser response event listener
526
+ * @param name - The name of the response handler
527
+ */
528
+ removeResponseEventListener(name) {
529
+ this._webRtcController.responseController.removeResponseEventListener(name);
530
+ }
531
+ /**
532
+ * Dispatch a new event.
533
+ * @param e event
534
+ * @returns
535
+ */
536
+ dispatchEvent(e) {
537
+ return this._eventEmitter.dispatchEvent(e);
538
+ }
539
+ /**
540
+ * Register an event handler.
541
+ * @param type event name
542
+ * @param listener event handler function
543
+ */
544
+ addEventListener(type, listener) {
545
+ this._eventEmitter.addEventListener(type, listener);
546
+ }
547
+ /**
548
+ * Remove an event handler.
549
+ * @param type event name
550
+ * @param listener event handler function
551
+ */
552
+ removeEventListener(type, listener) {
553
+ this._eventEmitter.removeEventListener(type, listener);
554
+ }
555
+ /**
556
+ * Enable/disable XR mode.
557
+ */
558
+ toggleXR() {
559
+ this.webXrController.xrClicked();
560
+ }
561
+ /**
562
+ * Pass in a function to generate a signalling server URL.
563
+ * This function is useful if you need to programmatically construct your signalling server URL.
564
+ * @param signallingUrlBuilderFunc A function that generates a signalling server url.
565
+ */
566
+ setSignallingUrlBuilder(signallingUrlBuilderFunc) {
567
+ this._webRtcController.signallingUrlBuilder = signallingUrlBuilderFunc;
568
+ }
569
+ get webRtcController() {
570
+ return this._webRtcController;
571
+ }
572
+ /**
573
+ * Public getter for the websocket controller. Access to this property allows you to send
574
+ * custom websocket messages.
575
+ */
576
+ get signallingProtocol() {
577
+ return this._webRtcController.protocol;
578
+ }
579
+ /**
580
+ * Public getter for the webXrController controller. Used for all XR features.
581
+ */
582
+ get webXrController() {
583
+ return this._webXrController;
584
+ }
585
+ registerMessageHandler(name, direction, handler) {
586
+ if (direction === MessageDirection.FromStreamer && typeof handler === 'undefined') {
587
+ Logger.Warning(`Unable to register an undefined handler for ${name}`);
588
+ return;
589
+ }
590
+ if (direction === MessageDirection.ToStreamer && typeof handler === 'undefined') {
591
+ this._webRtcController.streamMessageController.registerMessageHandler(direction, name, (data) => this._webRtcController.sendMessageController.sendMessageToStreamer(name, data));
592
+ }
593
+ else {
594
+ this._webRtcController.streamMessageController.registerMessageHandler(direction, name, (data) => handler(data));
595
+ }
596
+ }
597
+ get toStreamerHandlers() {
598
+ return this._webRtcController.streamMessageController.toStreamerHandlers;
599
+ }
600
+ isReconnecting() {
601
+ return this._webRtcController.isReconnecting;
602
+ }
603
+ }
604
604
  //# sourceMappingURL=PixelStreaming.js.map