@yang__yj/pixelstreaming-core 1.0.0 → 1.0.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.
Files changed (237) hide show
  1. package/.cspell.json +48 -0
  2. package/.eslintignore +8 -0
  3. package/.eslintrc.js +8 -0
  4. package/.prettierignore +0 -0
  5. package/.prettierrc.json +6 -0
  6. package/coverage/clover.xml +3480 -0
  7. package/coverage/coverage-final.json +62 -0
  8. package/coverage/lcov-report/base.css +224 -0
  9. package/coverage/lcov-report/block-navigation.js +87 -0
  10. package/coverage/lcov-report/favicon.png +0 -0
  11. package/coverage/lcov-report/index.html +356 -0
  12. package/coverage/lcov-report/prettify.css +1 -0
  13. package/coverage/lcov-report/prettify.js +2 -0
  14. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  15. package/coverage/lcov-report/sorter.js +196 -0
  16. package/coverage/lcov-report/src/AFK/AFKController.ts.html +559 -0
  17. package/coverage/lcov-report/src/AFK/index.html +116 -0
  18. package/coverage/lcov-report/src/Config/Config.ts.html +2764 -0
  19. package/coverage/lcov-report/src/Config/SettingBase.ts.html +280 -0
  20. package/coverage/lcov-report/src/Config/SettingFlag.ts.html +382 -0
  21. package/coverage/lcov-report/src/Config/SettingNumber.ts.html +418 -0
  22. package/coverage/lcov-report/src/Config/SettingOption.ts.html +424 -0
  23. package/coverage/lcov-report/src/Config/SettingText.ts.html +331 -0
  24. package/coverage/lcov-report/src/Config/index.html +191 -0
  25. package/coverage/lcov-report/src/DataChannel/DataChannelController.ts.html +499 -0
  26. package/coverage/lcov-report/src/DataChannel/DataChannelSender.ts.html +262 -0
  27. package/coverage/lcov-report/src/DataChannel/InitialSettings.ts.html +268 -0
  28. package/coverage/lcov-report/src/DataChannel/LatencyTestResults.ts.html +313 -0
  29. package/coverage/lcov-report/src/DataChannel/index.html +161 -0
  30. package/coverage/lcov-report/src/FreezeFrame/FreezeFrame.ts.html +427 -0
  31. package/coverage/lcov-report/src/FreezeFrame/FreezeFrameController.ts.html +427 -0
  32. package/coverage/lcov-report/src/FreezeFrame/index.html +131 -0
  33. package/coverage/lcov-report/src/Inputs/FakeTouchController.ts.html +682 -0
  34. package/coverage/lcov-report/src/Inputs/GamepadController.ts.html +985 -0
  35. package/coverage/lcov-report/src/Inputs/HoveringMouseEvents.ts.html +688 -0
  36. package/coverage/lcov-report/src/Inputs/InputClassesFactory.ts.html +505 -0
  37. package/coverage/lcov-report/src/Inputs/KeyboardController.ts.html +1048 -0
  38. package/coverage/lcov-report/src/Inputs/LockedMouseEvents.ts.html +946 -0
  39. package/coverage/lcov-report/src/Inputs/MouseButtons.ts.html +160 -0
  40. package/coverage/lcov-report/src/Inputs/MouseController.ts.html +1171 -0
  41. package/coverage/lcov-report/src/Inputs/SpecialKeyCodes.ts.html +133 -0
  42. package/coverage/lcov-report/src/Inputs/TouchController.ts.html +712 -0
  43. package/coverage/lcov-report/src/Inputs/XRGamepadController.ts.html +463 -0
  44. package/coverage/lcov-report/src/Inputs/index.html +266 -0
  45. package/coverage/lcov-report/src/Logger/Logger.ts.html +325 -0
  46. package/coverage/lcov-report/src/Logger/index.html +116 -0
  47. package/coverage/lcov-report/src/PeerConnectionController/AggregatedStats.ts.html +1018 -0
  48. package/coverage/lcov-report/src/PeerConnectionController/CandidatePairStats.ts.html +136 -0
  49. package/coverage/lcov-report/src/PeerConnectionController/CandidateStat.ts.html +124 -0
  50. package/coverage/lcov-report/src/PeerConnectionController/DataChannelStats.ts.html +136 -0
  51. package/coverage/lcov-report/src/PeerConnectionController/InboundRTPStats.ts.html +547 -0
  52. package/coverage/lcov-report/src/PeerConnectionController/OutBoundRTPStats.ts.html +163 -0
  53. package/coverage/lcov-report/src/PeerConnectionController/PeerConnectionController.ts.html +1795 -0
  54. package/coverage/lcov-report/src/PeerConnectionController/SessionStats.ts.html +115 -0
  55. package/coverage/lcov-report/src/PeerConnectionController/StreamStats.ts.html +118 -0
  56. package/coverage/lcov-report/src/PeerConnectionController/index.html +236 -0
  57. package/coverage/lcov-report/src/PixelStreaming/PixelStreaming.ts.html +2269 -0
  58. package/coverage/lcov-report/src/PixelStreaming/index.html +116 -0
  59. package/coverage/lcov-report/src/UI/OnScreenKeyboard.ts.html +376 -0
  60. package/coverage/lcov-report/src/UI/index.html +116 -0
  61. package/coverage/lcov-report/src/UeInstanceMessage/ResponseController.ts.html +226 -0
  62. package/coverage/lcov-report/src/UeInstanceMessage/SendDescriptorController.ts.html +346 -0
  63. package/coverage/lcov-report/src/UeInstanceMessage/SendMessageController.ts.html +364 -0
  64. package/coverage/lcov-report/src/UeInstanceMessage/StreamMessageController.ts.html +862 -0
  65. package/coverage/lcov-report/src/UeInstanceMessage/ToStreamerMessagesController.ts.html +271 -0
  66. package/coverage/lcov-report/src/UeInstanceMessage/TwoWayMap.ts.html +241 -0
  67. package/coverage/lcov-report/src/UeInstanceMessage/index.html +191 -0
  68. package/coverage/lcov-report/src/Util/CoordinateConverter.ts.html +952 -0
  69. package/coverage/lcov-report/src/Util/EventEmitter.ts.html +1705 -0
  70. package/coverage/lcov-report/src/Util/EventListenerTracker.ts.html +172 -0
  71. package/coverage/lcov-report/src/Util/FileUtil.ts.html +505 -0
  72. package/coverage/lcov-report/src/Util/WebGLUtils.ts.html +232 -0
  73. package/coverage/lcov-report/src/Util/WebXRUtils.ts.html +160 -0
  74. package/coverage/lcov-report/src/Util/index.html +191 -0
  75. package/coverage/lcov-report/src/VideoPlayer/StreamController.ts.html +349 -0
  76. package/coverage/lcov-report/src/VideoPlayer/VideoPlayer.ts.html +799 -0
  77. package/coverage/lcov-report/src/VideoPlayer/index.html +131 -0
  78. package/coverage/lcov-report/src/WebRtcPlayer/WebRtcPlayerController.ts.html +6199 -0
  79. package/coverage/lcov-report/src/WebRtcPlayer/index.html +116 -0
  80. package/coverage/lcov-report/src/WebSockets/MessageReceive.ts.html +352 -0
  81. package/coverage/lcov-report/src/WebSockets/MessageSend.ts.html +604 -0
  82. package/coverage/lcov-report/src/WebSockets/SignallingProtocol.ts.html +622 -0
  83. package/coverage/lcov-report/src/WebSockets/WebSocketController.ts.html +844 -0
  84. package/coverage/lcov-report/src/WebSockets/index.html +161 -0
  85. package/coverage/lcov-report/src/WebXR/WebXRController.ts.html +1042 -0
  86. package/coverage/lcov-report/src/WebXR/index.html +116 -0
  87. package/coverage/lcov-report/src/__test__/index.html +161 -0
  88. package/coverage/lcov-report/src/__test__/mockMediaStream.ts.html +457 -0
  89. package/coverage/lcov-report/src/__test__/mockRTCPeerConnection.ts.html +1126 -0
  90. package/coverage/lcov-report/src/__test__/mockRTCRtpReceiver.ts.html +151 -0
  91. package/coverage/lcov-report/src/__test__/mockWebSocket.ts.html +475 -0
  92. package/coverage/lcov-report/src/index.html +116 -0
  93. package/coverage/lcov-report/src/pixelstreamingfrontend.ts.html +232 -0
  94. package/coverage/lcov.info +6458 -0
  95. package/jest.config.js +18 -0
  96. package/package.json +46 -18
  97. package/readme.md +15 -0
  98. package/src/AFK/AFKController.test.ts +162 -0
  99. package/src/AFK/AFKController.ts +158 -0
  100. package/src/Config/Config.test.ts +222 -0
  101. package/src/Config/Config.ts +909 -0
  102. package/src/Config/SettingBase.ts +65 -0
  103. package/src/Config/SettingFlag.ts +99 -0
  104. package/src/Config/SettingNumber.ts +111 -0
  105. package/src/Config/SettingOption.ts +124 -0
  106. package/src/Config/SettingText.ts +82 -0
  107. package/src/DataChannel/DataChannelController.ts +138 -0
  108. package/src/DataChannel/DataChannelLatencyTestController.ts +129 -0
  109. package/src/DataChannel/DataChannelLatencyTestResults.ts +67 -0
  110. package/src/DataChannel/DataChannelSender.ts +59 -0
  111. package/src/DataChannel/InitialSettings.ts +61 -0
  112. package/src/DataChannel/LatencyTestResults.ts +76 -0
  113. package/src/FreezeFrame/FreezeFrame.ts +114 -0
  114. package/src/FreezeFrame/FreezeFrameController.ts +114 -0
  115. package/src/Inputs/FakeTouchController.ts +199 -0
  116. package/src/Inputs/GamepadController.ts +300 -0
  117. package/src/Inputs/GamepadTypes.ts +10 -0
  118. package/src/Inputs/HoveringMouseEvents.ts +192 -0
  119. package/src/Inputs/IMouseEvents.ts +64 -0
  120. package/src/Inputs/ITouchController.ts +29 -0
  121. package/src/Inputs/InputClassesFactory.ts +140 -0
  122. package/src/Inputs/KeyboardController.ts +318 -0
  123. package/src/Inputs/LockedMouseEvents.ts +287 -0
  124. package/src/Inputs/MouseButtons.ts +25 -0
  125. package/src/Inputs/MouseController.ts +362 -0
  126. package/src/Inputs/SpecialKeyCodes.ts +16 -0
  127. package/src/Inputs/TouchController.ts +253 -0
  128. package/src/Inputs/XRGamepadController.ts +126 -0
  129. package/src/Logger/Logger.ts +80 -0
  130. package/src/PeerConnectionController/AggregatedStats.ts +311 -0
  131. package/src/PeerConnectionController/CandidatePairStats.ts +17 -0
  132. package/src/PeerConnectionController/CandidateStat.ts +13 -0
  133. package/src/PeerConnectionController/CodecStats.ts +19 -0
  134. package/src/PeerConnectionController/DataChannelStats.ts +17 -0
  135. package/src/PeerConnectionController/InboundRTPStats.ts +154 -0
  136. package/src/PeerConnectionController/InboundTrackStats.ts +34 -0
  137. package/src/PeerConnectionController/OutBoundRTPStats.ts +26 -0
  138. package/src/PeerConnectionController/PeerConnectionController.ts +563 -0
  139. package/src/PeerConnectionController/SessionStats.ts +10 -0
  140. package/src/PeerConnectionController/StreamStats.ts +11 -0
  141. package/src/PixelStreaming/PixelStreaming.test.ts +624 -0
  142. package/src/PixelStreaming/PixelStreaming.ts +847 -0
  143. package/src/UI/OnScreenKeyboard.ts +97 -0
  144. package/src/UeInstanceMessage/ResponseController.ts +47 -0
  145. package/src/UeInstanceMessage/SendMessageController.ts +154 -0
  146. package/src/UeInstanceMessage/StreamMessageController.ts +233 -0
  147. package/src/UeInstanceMessage/ToStreamerMessagesController.ts +62 -0
  148. package/src/Util/CoordinateConverter.ts +289 -0
  149. package/src/Util/EventEmitter.ts +595 -0
  150. package/src/Util/EventListenerTracker.ts +29 -0
  151. package/src/Util/FileUtil.ts +140 -0
  152. package/src/Util/RTCUtils.ts +41 -0
  153. package/src/Util/WebGLUtils.ts +49 -0
  154. package/src/Util/WebXRUtils.ts +25 -0
  155. package/src/VideoPlayer/StreamController.ts +89 -0
  156. package/src/VideoPlayer/VideoPlayer.ts +246 -0
  157. package/src/WebRtcPlayer/WebRtcPlayerController.ts +2144 -0
  158. package/src/WebSockets/MessageReceive.ts +89 -0
  159. package/src/WebSockets/MessageSend.ts +185 -0
  160. package/src/WebSockets/SignallingProtocol.ts +180 -0
  161. package/src/WebSockets/WebSocketController.ts +267 -0
  162. package/src/WebXR/WebXRController.ts +319 -0
  163. package/src/__test__/mockMediaStream.ts +124 -0
  164. package/src/__test__/mockRTCPeerConnection.ts +347 -0
  165. package/src/__test__/mockRTCRtpReceiver.ts +22 -0
  166. package/src/__test__/mockWebSocket.ts +130 -0
  167. package/src/pixelstreamingfrontend.ts +50 -0
  168. package/tsconfig.jest.json +8 -0
  169. package/tsconfig.json +24 -0
  170. package/webpack.common.js +35 -0
  171. package/webpack.dev.js +35 -0
  172. package/webpack.prod.js +36 -0
  173. package/yang__yj-pixelstreaming-core-1.0.1.tgz +0 -0
  174. /package/{library/dist → dist}/lib-pixelstreamingfrontend.esm.js +0 -0
  175. /package/{library/dist → dist}/lib-pixelstreamingfrontend.js +0 -0
  176. /package/{library/types → types}/AFK/AFKController.d.ts +0 -0
  177. /package/{library/types → types}/Config/Config.d.ts +0 -0
  178. /package/{library/types → types}/Config/SettingBase.d.ts +0 -0
  179. /package/{library/types → types}/Config/SettingFlag.d.ts +0 -0
  180. /package/{library/types → types}/Config/SettingNumber.d.ts +0 -0
  181. /package/{library/types → types}/Config/SettingOption.d.ts +0 -0
  182. /package/{library/types → types}/Config/SettingText.d.ts +0 -0
  183. /package/{library/types → types}/DataChannel/DataChannelController.d.ts +0 -0
  184. /package/{library/types → types}/DataChannel/DataChannelSender.d.ts +0 -0
  185. /package/{library/types → types}/DataChannel/InitialSettings.d.ts +0 -0
  186. /package/{library/types → types}/DataChannel/LatencyTestResults.d.ts +0 -0
  187. /package/{library/types → types}/FreezeFrame/FreezeFrame.d.ts +0 -0
  188. /package/{library/types → types}/FreezeFrame/FreezeFrameController.d.ts +0 -0
  189. /package/{library/types → types}/Inputs/FakeTouchController.d.ts +0 -0
  190. /package/{library/types → types}/Inputs/GamepadController.d.ts +0 -0
  191. /package/{library/types → types}/Inputs/GamepadTypes.d.ts +0 -0
  192. /package/{library/types → types}/Inputs/HoveringMouseEvents.d.ts +0 -0
  193. /package/{library/types → types}/Inputs/IMouseEvents.d.ts +0 -0
  194. /package/{library/types → types}/Inputs/ITouchController.d.ts +0 -0
  195. /package/{library/types → types}/Inputs/InputClassesFactory.d.ts +0 -0
  196. /package/{library/types → types}/Inputs/KeyboardController.d.ts +0 -0
  197. /package/{library/types → types}/Inputs/LockedMouseEvents.d.ts +0 -0
  198. /package/{library/types → types}/Inputs/MouseButtons.d.ts +0 -0
  199. /package/{library/types → types}/Inputs/MouseController.d.ts +0 -0
  200. /package/{library/types → types}/Inputs/SpecialKeyCodes.d.ts +0 -0
  201. /package/{library/types → types}/Inputs/TouchController.d.ts +0 -0
  202. /package/{library/types → types}/Inputs/XRGamepadController.d.ts +0 -0
  203. /package/{library/types → types}/Logger/Logger.d.ts +0 -0
  204. /package/{library/types → types}/PeerConnectionController/AggregatedStats.d.ts +0 -0
  205. /package/{library/types → types}/PeerConnectionController/CandidatePairStats.d.ts +0 -0
  206. /package/{library/types → types}/PeerConnectionController/CandidateStat.d.ts +0 -0
  207. /package/{library/types → types}/PeerConnectionController/CodecStats.d.ts +0 -0
  208. /package/{library/types → types}/PeerConnectionController/DataChannelStats.d.ts +0 -0
  209. /package/{library/types → types}/PeerConnectionController/InboundRTPStats.d.ts +0 -0
  210. /package/{library/types → types}/PeerConnectionController/InboundTrackStats.d.ts +0 -0
  211. /package/{library/types → types}/PeerConnectionController/OutBoundRTPStats.d.ts +0 -0
  212. /package/{library/types → types}/PeerConnectionController/PeerConnectionController.d.ts +0 -0
  213. /package/{library/types → types}/PeerConnectionController/SessionStats.d.ts +0 -0
  214. /package/{library/types → types}/PeerConnectionController/StreamStats.d.ts +0 -0
  215. /package/{library/types → types}/PixelStreaming/PixelStreaming.d.ts +0 -0
  216. /package/{library/types → types}/UI/OnScreenKeyboard.d.ts +0 -0
  217. /package/{library/types → types}/UeInstanceMessage/ResponseController.d.ts +0 -0
  218. /package/{library/types → types}/UeInstanceMessage/SendDescriptorController.d.ts +0 -0
  219. /package/{library/types → types}/UeInstanceMessage/SendMessageController.d.ts +0 -0
  220. /package/{library/types → types}/UeInstanceMessage/StreamMessageController.d.ts +0 -0
  221. /package/{library/types → types}/UeInstanceMessage/ToStreamerMessagesController.d.ts +0 -0
  222. /package/{library/types → types}/UeInstanceMessage/TwoWayMap.d.ts +0 -0
  223. /package/{library/types → types}/Util/CoordinateConverter.d.ts +0 -0
  224. /package/{library/types → types}/Util/EventEmitter.d.ts +0 -0
  225. /package/{library/types → types}/Util/EventListenerTracker.d.ts +0 -0
  226. /package/{library/types → types}/Util/FileUtil.d.ts +0 -0
  227. /package/{library/types → types}/Util/WebGLUtils.d.ts +0 -0
  228. /package/{library/types → types}/Util/WebXRUtils.d.ts +0 -0
  229. /package/{library/types → types}/VideoPlayer/StreamController.d.ts +0 -0
  230. /package/{library/types → types}/VideoPlayer/VideoPlayer.d.ts +0 -0
  231. /package/{library/types → types}/WebRtcPlayer/WebRtcPlayerController.d.ts +0 -0
  232. /package/{library/types → types}/WebSockets/MessageReceive.d.ts +0 -0
  233. /package/{library/types → types}/WebSockets/MessageSend.d.ts +0 -0
  234. /package/{library/types → types}/WebSockets/SignallingProtocol.d.ts +0 -0
  235. /package/{library/types → types}/WebSockets/WebSocketController.d.ts +0 -0
  236. /package/{library/types → types}/WebXR/WebXRController.d.ts +0 -0
  237. /package/{library/types → types}/pixelstreamingfrontend.d.ts +0 -0
package/jest.config.js ADDED
@@ -0,0 +1,18 @@
1
+ module.exports = {
2
+ preset: "ts-jest/presets/js-with-ts",
3
+ testEnvironment: "jsdom",
4
+ transform: {
5
+ "^.+\\.tsx?$": [
6
+ "ts-jest",
7
+ {
8
+ tsconfig: "tsconfig.jest.json",
9
+ },
10
+ ],
11
+ },
12
+ modulePathIgnorePatterns: ["<rootDir>/build/"],
13
+ testPathIgnorePatterns: ["<rootDir>/build/", "/node_modules/"],
14
+ globals: {
15
+ TextDecoder: TextDecoder,
16
+ TextEncoder: TextEncoder,
17
+ }
18
+ };
package/package.json CHANGED
@@ -1,18 +1,46 @@
1
- {
2
- "name": "@yang__yj/pixelstreaming-core",
3
- "version": "1.0.0",
4
- "main": "library/dist/lib-pixelstreamingfrontend.js",
5
- "module": "library/dist/lib-pixelstreamingfrontend.esm.js",
6
- "types": "library/types/pixelstreamingfrontend.d.ts",
7
- "files": [
8
- "library/dist",
9
- "library/types"
10
- ],
11
- "scripts": {
12
- "prepublishOnly": "echo using existing build"
13
- },
14
- "publishConfig": {
15
- "access": "public"
16
- },
17
- "license": "ISC"
18
- }
1
+ {
2
+ "name": "@yang__yj/pixelstreaming-core",
3
+ "version": "1.0.1",
4
+ "description": "Frontend library for Unreal Engine 5.3 Pixel Streaming",
5
+ "main": "dist/lib-pixelstreamingfrontend.js",
6
+ "module": "dist/lib-pixelstreamingfrontend.esm.js",
7
+ "types": "types/pixelstreamingfrontend.d.ts",
8
+ "sideEffects": false,
9
+ "scripts": {
10
+ "compile": "tsc --build --clean && tsc",
11
+ "build": "npx webpack --config webpack.prod.js",
12
+ "build-dev": "npx webpack --config webpack.dev.js",
13
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
14
+ "test": "jest --detectOpenHandles --coverage=true",
15
+ "spellcheck": "cspell \"{README.md,.github/*.md,src/**/*.ts}\""
16
+ },
17
+ "devDependencies": {
18
+ "@types/jest": "27.5.1",
19
+ "@types/webxr": "^0.5.1",
20
+ "@typescript-eslint/eslint-plugin": "^5.16.0",
21
+ "@typescript-eslint/parser": "^5.16.0",
22
+ "cspell": "^4.1.0",
23
+ "eslint": "^8.11.0",
24
+ "jest": "^27.5.1",
25
+ "jest-environment-jsdom": "27.5.1",
26
+ "prettier": "2.8.3",
27
+ "ts-jest": "27.1.5",
28
+ "ts-loader": "^9.4.2",
29
+ "typedoc": "^0.23.24",
30
+ "typescript": "^4.9.4",
31
+ "webpack": "^5.75.0",
32
+ "webpack-cli": "^5.0.1"
33
+ },
34
+ "dependencies": {
35
+ "sdp": "^3.1.0"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/EpicGames/PixelStreamingInfrastructure.git"
40
+ },
41
+ "author": "Epic Games",
42
+ "license": "MIT",
43
+ "publishConfig": {
44
+ "access": "public"
45
+ }
46
+ }
package/readme.md ADDED
@@ -0,0 +1,15 @@
1
+ ## lib-pixelstreamingfrontend
2
+
3
+ The core library for the browser/client side of Pixel Streaming experiences. **This library contains no UI.**
4
+
5
+ See [lib-pixelstreamingfrontend-ui](/Frontend/implementations/typescript) for an example of how to build UI on top of this library.
6
+
7
+ ### Key features
8
+ - Create a websocket connection to communicate with the signalling server.
9
+ - Create a WebRTC player that displays the Unreal Engine video and audio.
10
+ - Handling of input from the user and transmitting it back to Unreal Engine.
11
+ - Opens a datachannel connection sending and receiving custom data (in addition to input).
12
+
13
+ ### Adding it to your project
14
+ `npm i @epicgames-ps/lib-pixelstreamingfrontend-ue5.3`
15
+
@@ -0,0 +1,162 @@
1
+ import { Config, Flags, NumericParameters } from '../Config/Config';
2
+ import { PixelStreaming } from '../PixelStreaming/PixelStreaming';
3
+ import { AfkTimedOutEvent, AfkWarningActivateEvent, AfkWarningUpdateEvent, AfkWarningDeactivateEvent } from '../Util/EventEmitter';
4
+ import { mockRTCRtpReceiver, unmockRTCRtpReceiver } from '../__test__/mockRTCRtpReceiver';
5
+ import {
6
+ AFKController
7
+ } from './AFKController';
8
+
9
+ describe('AFKController', () => {
10
+ let mockPixelStreaming: PixelStreaming;
11
+
12
+ beforeEach(() => {
13
+ mockRTCRtpReceiver();
14
+ jest.useFakeTimers();
15
+ mockPixelStreaming = {
16
+ dispatchEvent: jest.fn()
17
+ } as any as PixelStreaming;
18
+ });
19
+
20
+ afterEach(() => {
21
+ unmockRTCRtpReceiver();
22
+ jest.resetAllMocks();
23
+ });
24
+
25
+ it('should not activate AFK timer if it has been disabled from settings', () => {
26
+ const config = new Config({ initialSettings: { [Flags.AFKDetection]: false } });
27
+ const onDismissAfk = jest.fn();
28
+ const afkController = new AFKController(config, mockPixelStreaming, onDismissAfk);
29
+
30
+ afkController.startAfkWarningTimer();
31
+ expect(afkController.active).toBe(false);
32
+
33
+ jest.advanceTimersByTime(1000000 * 1000);
34
+ expect(mockPixelStreaming.dispatchEvent).not.toHaveBeenCalled();
35
+ });
36
+
37
+ it('should activate AFK timer and trigger it after specified delay if it has been enabled from settings', () => {
38
+ const timeoutSeconds = 100;
39
+
40
+ const config = new Config({ initialSettings: { [Flags.AFKDetection]: true, [NumericParameters.AFKTimeoutSecs]: timeoutSeconds} });
41
+ const onDismissAfk = jest.fn();
42
+ const afkController = new AFKController(config, mockPixelStreaming, onDismissAfk);
43
+
44
+ afkController.startAfkWarningTimer();
45
+ expect(afkController.active).toBe(true);
46
+
47
+ // Advance to 1 second before AFK event:
48
+ jest.advanceTimersByTime((timeoutSeconds - 1) * 1000);
49
+ expect(mockPixelStreaming.dispatchEvent).not.toHaveBeenCalled();
50
+
51
+ // advance 1 more second to trigger AFK warning
52
+ jest.advanceTimersByTime(1000);
53
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningActivateEvent({
54
+ countDown: 0,
55
+ dismissAfk: expect.anything()
56
+ }));
57
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
58
+ countDown: 10,
59
+ }));
60
+
61
+ // advance 10 more seconds to trigger AFK countdown updates and eventually timeout
62
+ jest.advanceTimersByTime(10 * 1000);
63
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
64
+ countDown: 9,
65
+ }));
66
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
67
+ countDown: 8,
68
+ }));
69
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
70
+ countDown: 7,
71
+ }));
72
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
73
+ countDown: 6,
74
+ }));
75
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
76
+ countDown: 5,
77
+ }));
78
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
79
+ countDown: 4,
80
+ }));
81
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
82
+ countDown: 3,
83
+ }));
84
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
85
+ countDown: 2,
86
+ }));
87
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
88
+ countDown: 1,
89
+ }));
90
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkTimedOutEvent());
91
+ });
92
+
93
+ it('should postpone AFK activation each time resetAfkWarningTimer is called', () => {
94
+ const timeoutSeconds = 100;
95
+
96
+ const config = new Config({ initialSettings: { [Flags.AFKDetection]: true, [NumericParameters.AFKTimeoutSecs]: timeoutSeconds} });
97
+ const onDismissAfk = jest.fn();
98
+ const afkController = new AFKController(config, mockPixelStreaming, onDismissAfk);
99
+
100
+ afkController.startAfkWarningTimer();
101
+
102
+ // Advance to 1 second before AFK event:
103
+ jest.advanceTimersByTime((timeoutSeconds - 1) * 1000);
104
+ expect(mockPixelStreaming.dispatchEvent).not.toHaveBeenCalled();
105
+
106
+ afkController.resetAfkWarningTimer();
107
+
108
+ // advance 1 more second and ensure that AFK warning is not triggered since reset was called
109
+ jest.advanceTimersByTime(1000);
110
+ expect(mockPixelStreaming.dispatchEvent).not.toHaveBeenCalled();
111
+
112
+ // reset AFK timer once more and ensure it is triggered exactly after timeoutSeconds
113
+ afkController.resetAfkWarningTimer();
114
+
115
+ // Advance to 1 second before AFK event:
116
+ jest.advanceTimersByTime((timeoutSeconds - 1) * 1000);
117
+ expect(mockPixelStreaming.dispatchEvent).not.toHaveBeenCalled();
118
+
119
+ // advance 1 more second to trigger AFK warning
120
+ jest.advanceTimersByTime(1000);
121
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningActivateEvent({
122
+ countDown: 0,
123
+ dismissAfk: expect.anything()
124
+ }));
125
+ });
126
+
127
+ it('should dismiss AFK warning countdown if onAfkClick is called', () => {
128
+ const timeoutSeconds = 100;
129
+
130
+ const config = new Config({ initialSettings: { [Flags.AFKDetection]: true, [NumericParameters.AFKTimeoutSecs]: timeoutSeconds} });
131
+ const onDismissAfk = jest.fn();
132
+ const afkController = new AFKController(config, mockPixelStreaming, onDismissAfk);
133
+
134
+ afkController.startAfkWarningTimer();
135
+
136
+ // Advance to AFK event:
137
+ jest.advanceTimersByTime(timeoutSeconds * 1000);
138
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningActivateEvent({
139
+ countDown: 0,
140
+ dismissAfk: expect.anything()
141
+ }));
142
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
143
+ countDown: 10,
144
+ }));
145
+
146
+ // Advance one more second and call onAfkClick
147
+ jest.advanceTimersByTime(1000);
148
+
149
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningUpdateEvent({
150
+ countDown: 9,
151
+ }));
152
+
153
+ afkController.onAfkClick();
154
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledWith(new AfkWarningDeactivateEvent());
155
+
156
+ // advance 10 more seconds and ensure there are no more countdown/timeout events emitted
157
+ jest.advanceTimersByTime(10 * 1000);
158
+ expect(mockPixelStreaming.dispatchEvent).toHaveBeenCalledTimes(4);
159
+ });
160
+
161
+
162
+ });
@@ -0,0 +1,158 @@
1
+ // Copyright Epic Games, Inc. All Rights Reserved.
2
+
3
+ import { Config, Flags, NumericParameters } from '../Config/Config';
4
+ import { Logger } from '../Logger/Logger';
5
+ import { PixelStreaming } from '../PixelStreaming/PixelStreaming';
6
+ import {
7
+ AfkTimedOutEvent,
8
+ AfkWarningActivateEvent,
9
+ AfkWarningDeactivateEvent,
10
+ AfkWarningUpdateEvent
11
+ } from '../Util/EventEmitter';
12
+
13
+ export class AFKController {
14
+ // time out logic details
15
+ closeTimeout = 10;
16
+ active = false;
17
+ countdownActive = false;
18
+ warnTimer: ReturnType<typeof setTimeout> = undefined;
19
+ countDown = 0;
20
+ countDownTimer: ReturnType<typeof setInterval> = undefined;
21
+ config: Config;
22
+ pixelStreaming: PixelStreaming;
23
+ onDismissAfk: () => void;
24
+
25
+ onAFKTimedOutCallback: () => void;
26
+
27
+ constructor(
28
+ config: Config,
29
+ pixelStreaming: PixelStreaming,
30
+ onDismissAfk: () => void
31
+ ) {
32
+ this.config = config;
33
+ this.pixelStreaming = pixelStreaming;
34
+ this.onDismissAfk = onDismissAfk;
35
+ this.onAFKTimedOutCallback = () => {
36
+ console.log(
37
+ 'AFK timed out, did you want to override this callback?'
38
+ );
39
+ };
40
+ }
41
+
42
+ /**
43
+ * The methods that occur when an afk event listener is clicked
44
+ */
45
+ onAfkClick() {
46
+ clearInterval(this.countDownTimer);
47
+
48
+ if (this.active || this.countdownActive) {
49
+ this.startAfkWarningTimer();
50
+ this.pixelStreaming.dispatchEvent(
51
+ new AfkWarningDeactivateEvent()
52
+ );
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Start the warning timer if a timeout is set greater that 0 seconds
58
+ */
59
+ startAfkWarningTimer() {
60
+ if (
61
+ this.config.getNumericSettingValue(
62
+ NumericParameters.AFKTimeoutSecs
63
+ ) > 0 &&
64
+ this.config.isFlagEnabled(Flags.AFKDetection)
65
+ ) {
66
+ this.active = true;
67
+ } else {
68
+ this.active = false;
69
+ }
70
+ this.resetAfkWarningTimer();
71
+ }
72
+
73
+ /**
74
+ * Stop the afk warning timer
75
+ */
76
+ stopAfkWarningTimer() {
77
+ this.active = false;
78
+ this.countdownActive = false;
79
+ clearTimeout(this.warnTimer);
80
+ clearInterval(this.countDownTimer);
81
+ }
82
+
83
+ /**
84
+ * Pause the timer which when elapsed will warn the user they are inactive.
85
+ */
86
+ pauseAfkWarningTimer() {
87
+ this.active = false;
88
+ }
89
+
90
+ /**
91
+ * If the user interacts then reset the warning timer.
92
+ */
93
+ resetAfkWarningTimer() {
94
+ if (this.active && this.config.isFlagEnabled(Flags.AFKDetection)) {
95
+ clearTimeout(this.warnTimer);
96
+ this.warnTimer = setTimeout(
97
+ () => this.activateAfkEvent(),
98
+ this.config.getNumericSettingValue(
99
+ NumericParameters.AFKTimeoutSecs
100
+ ) * 1000
101
+ );
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Show the AFK overlay and begin the countDown
107
+ */
108
+ activateAfkEvent() {
109
+ // Pause the timer while the user is looking at the inactivity warning overlay
110
+ this.pauseAfkWarningTimer();
111
+
112
+ // instantiate a new overlay
113
+ this.pixelStreaming.dispatchEvent(
114
+ new AfkWarningActivateEvent({
115
+ countDown: this.countDown,
116
+ dismissAfk: this.onDismissAfk
117
+ })
118
+ );
119
+
120
+ // update our countDown timer and overlay contents
121
+ this.countDown = this.closeTimeout;
122
+ this.countdownActive = true;
123
+ this.pixelStreaming.dispatchEvent(
124
+ new AfkWarningUpdateEvent({ countDown: this.countDown })
125
+ );
126
+
127
+ // if we are in locked mouse exit pointerlock
128
+ if (!this.config.isFlagEnabled(Flags.HoveringMouseMode)) {
129
+ // minor hack to alleviate ios not supporting pointerlock
130
+ if (document.exitPointerLock) {
131
+ document.exitPointerLock();
132
+ }
133
+ }
134
+
135
+ // reset our countDown interval accordingly
136
+ this.countDownTimer = setInterval(() => {
137
+ this.countDown--;
138
+ if (this.countDown == 0) {
139
+ // The user failed to click so hide the overlay and disconnect them.
140
+ this.pixelStreaming.dispatchEvent(
141
+ new AfkTimedOutEvent()
142
+ );
143
+ this.onAFKTimedOutCallback();
144
+ Logger.Log(
145
+ Logger.GetStackTrace(),
146
+ 'You have been disconnected due to inactivity'
147
+ );
148
+
149
+ // switch off the afk feature as stream has closed
150
+ this.stopAfkWarningTimer();
151
+ } else {
152
+ this.pixelStreaming.dispatchEvent(
153
+ new AfkWarningUpdateEvent({ countDown: this.countDown })
154
+ );
155
+ }
156
+ }, 1000);
157
+ }
158
+ }
@@ -0,0 +1,222 @@
1
+ import { mockRTCRtpReceiver, unmockRTCRtpReceiver } from '../__test__/mockRTCRtpReceiver';
2
+ import {
3
+ Config,
4
+ Flags,
5
+ FlagsKeys,
6
+ NumericParameters,
7
+ NumericParametersKeys,
8
+ OptionParameters,
9
+ OptionParametersKeys,
10
+ TextParameters,
11
+ TextParametersKeys
12
+ } from './Config';
13
+
14
+ const allFlags = Object.keys(Flags).map((key) => Flags[key as FlagsKeys]);
15
+ const allNumericParameters = Object.keys(NumericParameters).map(
16
+ (key) => NumericParameters[key as NumericParametersKeys]
17
+ );
18
+ const allTextParameters = Object.keys(TextParameters).map(
19
+ (key) => TextParameters[key as TextParametersKeys]
20
+ );
21
+ const allOptionParameters = Object.keys(OptionParameters).map(
22
+ (key) => OptionParameters[key as OptionParametersKeys]
23
+ );
24
+
25
+ const allParameters = [
26
+ ...allFlags,
27
+ ...allNumericParameters,
28
+ ...allTextParameters,
29
+ ...allOptionParameters
30
+ ];
31
+
32
+ describe('Config', () => {
33
+ beforeEach(() => {
34
+ mockRTCRtpReceiver();
35
+ });
36
+
37
+ afterEach(() => {
38
+ unmockRTCRtpReceiver();
39
+ jest.resetAllMocks();
40
+ });
41
+
42
+ it('should populate initial values for all settings when initialized without parameters', () => {
43
+ const config = new Config();
44
+
45
+ const settings = config.getSettings();
46
+ expect(Object.keys(settings)).toEqual(
47
+ expect.arrayContaining(allParameters)
48
+ );
49
+ });
50
+
51
+ it('should populate given initial setting values', () => {
52
+ const initialSettings = {
53
+ [Flags.AutoPlayVideo]: false,
54
+ [NumericParameters.WebRTCMaxBitrate]: 12345,
55
+ [TextParameters.SignallingServerUrl]: 'url'
56
+ };
57
+
58
+ const config = new Config({ initialSettings });
59
+
60
+ expect(config.isFlagEnabled(Flags.AutoPlayVideo)).toEqual(
61
+ initialSettings[Flags.AutoPlayVideo]
62
+ );
63
+ expect(
64
+ config.getNumericSettingValue(NumericParameters.WebRTCMaxBitrate)
65
+ ).toEqual(initialSettings[NumericParameters.WebRTCMaxBitrate]);
66
+ expect(
67
+ config.getTextSettingValue(TextParameters.SignallingServerUrl)
68
+ ).toEqual(initialSettings[TextParameters.SignallingServerUrl]);
69
+ });
70
+
71
+ it('should replace setting values when new settings are set with setSettings', () => {
72
+ const config = new Config();
73
+
74
+ const preferredCodecs = ['c1', 'c2', 'c3'];
75
+ config.setOptionSettingOptions(
76
+ OptionParameters.PreferredCodec,
77
+ preferredCodecs
78
+ );
79
+
80
+ const changedSettings = {
81
+ [Flags.AutoPlayVideo]: false,
82
+ [NumericParameters.WebRTCMaxBitrate]: 54321,
83
+ [TextParameters.SignallingServerUrl]: 'signalling-url',
84
+ [OptionParameters.PreferredCodec]: 'c2'
85
+ };
86
+
87
+ config.setSettings(changedSettings);
88
+
89
+ expect(config.isFlagEnabled(Flags.AutoPlayVideo)).toEqual(
90
+ changedSettings[Flags.AutoPlayVideo]
91
+ );
92
+ expect(
93
+ config.getNumericSettingValue(NumericParameters.WebRTCMaxBitrate)
94
+ ).toEqual(changedSettings[NumericParameters.WebRTCMaxBitrate]);
95
+ expect(
96
+ config.getTextSettingValue(TextParameters.SignallingServerUrl)
97
+ ).toEqual(changedSettings[TextParameters.SignallingServerUrl]);
98
+ expect(
99
+ config.getSettingOption(OptionParameters.PreferredCodec).selected
100
+ ).toEqual(changedSettings[OptionParameters.PreferredCodec]);
101
+ });
102
+
103
+ it('should replace setting values when new settings are set with set* setters', () => {
104
+ const config = new Config();
105
+
106
+ const preferredCodecs = ['c1', 'c2', 'c3'];
107
+ config.setOptionSettingOptions(
108
+ OptionParameters.PreferredCodec,
109
+ preferredCodecs
110
+ );
111
+
112
+ const changedSettings = {
113
+ [Flags.AutoPlayVideo]: false,
114
+ [NumericParameters.WebRTCMaxBitrate]: 54321,
115
+ [TextParameters.SignallingServerUrl]: 'signalling-url',
116
+ [OptionParameters.PreferredCodec]: 'c2'
117
+ };
118
+
119
+ config.setFlagEnabled(
120
+ Flags.AutoPlayVideo,
121
+ changedSettings[Flags.AutoPlayVideo]
122
+ );
123
+ config.setNumericSetting(
124
+ NumericParameters.WebRTCMaxBitrate,
125
+ changedSettings[NumericParameters.WebRTCMaxBitrate]
126
+ );
127
+ config.setTextSetting(
128
+ TextParameters.SignallingServerUrl,
129
+ changedSettings[TextParameters.SignallingServerUrl]
130
+ );
131
+ config.setOptionSettingValue(
132
+ OptionParameters.PreferredCodec,
133
+ changedSettings[OptionParameters.PreferredCodec]
134
+ );
135
+
136
+ expect(config.isFlagEnabled(Flags.AutoPlayVideo)).toEqual(
137
+ changedSettings[Flags.AutoPlayVideo]
138
+ );
139
+ expect(
140
+ config.getNumericSettingValue(NumericParameters.WebRTCMaxBitrate)
141
+ ).toEqual(changedSettings[NumericParameters.WebRTCMaxBitrate]);
142
+ expect(
143
+ config.getTextSettingValue(TextParameters.SignallingServerUrl)
144
+ ).toEqual(changedSettings[TextParameters.SignallingServerUrl]);
145
+ expect(
146
+ config.getSettingOption(OptionParameters.PreferredCodec).selected
147
+ ).toEqual(changedSettings[OptionParameters.PreferredCodec]);
148
+ });
149
+
150
+ it('should persist config changes to window.location URL when updateURLParams() is called', () => {
151
+ const config = new Config({ useUrlParams: true });
152
+
153
+ const preferredCodecs = ['c1', 'c2', 'c3'];
154
+ config.setOptionSettingOptions(
155
+ OptionParameters.PreferredCodec,
156
+ preferredCodecs
157
+ );
158
+
159
+ const changedSettings = {
160
+ [Flags.AutoPlayVideo]: false,
161
+ [NumericParameters.WebRTCMaxBitrate]: 54321,
162
+ [TextParameters.SignallingServerUrl]: 'signalling-url',
163
+ [OptionParameters.PreferredCodec]: 'c2'
164
+ };
165
+
166
+ config.setSettings(changedSettings);
167
+
168
+ config
169
+ .getFlags()
170
+ .find((setting) => setting.id === Flags.AutoPlayVideo)
171
+ ?.updateURLParams();
172
+ config
173
+ .getNumericSettings()
174
+ .find(
175
+ (setting) => setting.id === NumericParameters.WebRTCMaxBitrate
176
+ )
177
+ ?.updateURLParams();
178
+ config
179
+ .getTextSettings()
180
+ .find(
181
+ (setting) => setting.id === TextParameters.SignallingServerUrl
182
+ )
183
+ ?.updateURLParams();
184
+ config
185
+ .getOptionSettings()
186
+ .find((setting) => setting.id === OptionParameters.PreferredCodec)
187
+ ?.updateURLParams();
188
+
189
+ const urlParams = new URLSearchParams(window.location.search);
190
+
191
+ expect(urlParams.get(Flags.AutoPlayVideo)).toEqual(
192
+ changedSettings[Flags.AutoPlayVideo].toString()
193
+ );
194
+ expect(urlParams.get(NumericParameters.WebRTCMaxBitrate)).toEqual(
195
+ changedSettings[NumericParameters.WebRTCMaxBitrate].toString()
196
+ );
197
+ expect(urlParams.get(TextParameters.SignallingServerUrl)).toEqual(
198
+ changedSettings[TextParameters.SignallingServerUrl].toString()
199
+ );
200
+ expect(urlParams.get(OptionParameters.PreferredCodec)).toEqual(
201
+ changedSettings[OptionParameters.PreferredCodec].toString()
202
+ );
203
+ });
204
+
205
+ it('should read initial config from window.location URL if initialized with useUrlParams: true', () => {
206
+ window.history.replaceState(
207
+ {},
208
+ '',
209
+ 'http://localhost/?AutoPlayVideo=false&WebRTCMaxBitrate=43210&ss=signalling-url-from-url-param'
210
+ );
211
+
212
+ const config = new Config({ useUrlParams: true });
213
+
214
+ expect(config.isFlagEnabled(Flags.AutoPlayVideo)).toEqual(false);
215
+ expect(
216
+ config.getNumericSettingValue(NumericParameters.WebRTCMaxBitrate)
217
+ ).toEqual(43210);
218
+ expect(
219
+ config.getTextSettingValue(TextParameters.SignallingServerUrl)
220
+ ).toEqual('signalling-url-from-url-param');
221
+ });
222
+ });