speechrecorderng 3.6.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/esm2022/lib/action/action.mjs +73 -0
  2. package/{esm2020 → esm2022}/lib/audio/array_audio_buffer.mjs +163 -163
  3. package/{esm2020 → esm2022}/lib/audio/array_audio_buffer_input_stream.mjs +85 -85
  4. package/{esm2020 → esm2022}/lib/audio/array_audio_buffer_random_access_stream.mjs +15 -15
  5. package/esm2022/lib/audio/audio_data_holder.mjs +264 -0
  6. package/{esm2020 → esm2022}/lib/audio/audio_display.mjs +93 -93
  7. package/{esm2020 → esm2022}/lib/audio/audio_player.mjs +213 -213
  8. package/esm2022/lib/audio/capture/capture.mjs +855 -0
  9. package/esm2022/lib/audio/context.mjs +79 -0
  10. package/{esm2020 → esm2022}/lib/audio/dsp/level_measure.mjs +515 -515
  11. package/{esm2020 → esm2022}/lib/audio/format.mjs +16 -16
  12. package/esm2022/lib/audio/impl/wavformat.mjs +6 -0
  13. package/{esm2020 → esm2022}/lib/audio/impl/wavreader.mjs +133 -133
  14. package/esm2022/lib/audio/impl/wavwriter.mjs +105 -0
  15. package/esm2022/lib/audio/inddb_audio_buffer.mjs +508 -0
  16. package/{esm2020 → esm2022}/lib/audio/io/stream.mjs +58 -58
  17. package/esm2022/lib/audio/net_audio_buffer.mjs +293 -0
  18. package/{esm2020 → esm2022}/lib/audio/persistor.mjs +80 -80
  19. package/{esm2020 → esm2022}/lib/audio/playback/array_audio_buffer_source_node.mjs +125 -125
  20. package/esm2022/lib/audio/playback/audio_source_node.mjs +18 -0
  21. package/esm2022/lib/audio/playback/audio_source_worklet_module_loader.mjs +167 -0
  22. package/{esm2020 → esm2022}/lib/audio/playback/inddb_audio_buffer_source_node.mjs +166 -166
  23. package/{esm2020 → esm2022}/lib/audio/playback/net_audio_buffer_source_node.mjs +217 -217
  24. package/esm2022/lib/audio/playback/player.mjs +402 -0
  25. package/esm2022/lib/audio/ui/audio_canvas_layer_comp.mjs +347 -0
  26. package/{esm2020 → esm2022}/lib/audio/ui/audio_display_control.mjs +65 -65
  27. package/{esm2020 → esm2022}/lib/audio/ui/audio_display_scroll_pane.mjs +139 -139
  28. package/{esm2020 → esm2022}/lib/audio/ui/audiosignal.mjs +524 -524
  29. package/{esm2020 → esm2022}/lib/audio/ui/common.mjs +18 -18
  30. package/esm2022/lib/audio/ui/container.mjs +414 -0
  31. package/{esm2020 → esm2022}/lib/audio/ui/livelevel.mjs +352 -352
  32. package/esm2022/lib/audio/ui/scroll_pane_horizontal.mjs +11 -0
  33. package/esm2022/lib/audio/ui/sonagram.mjs +900 -0
  34. package/esm2022/lib/db/inddb.mjs +120 -0
  35. package/esm2022/lib/dsp/utils.mjs +48 -0
  36. package/{esm2020 → esm2022}/lib/io/BinaryReader.mjs +84 -84
  37. package/esm2022/lib/io/BinaryWriter.mjs +74 -0
  38. package/{esm2020 → esm2022}/lib/io/stream.mjs +258 -258
  39. package/{esm2020 → esm2022}/lib/math/2d/geometry.mjs +27 -27
  40. package/esm2022/lib/math/complex.mjs +58 -0
  41. package/{esm2020 → esm2022}/lib/math/dft.mjs +195 -195
  42. package/{esm2020 → esm2022}/lib/media/utils.mjs +13 -13
  43. package/esm2022/lib/net/uploader.mjs +367 -0
  44. package/{esm2020 → esm2022}/lib/recorder_component.mjs +64 -64
  45. package/esm2022/lib/speechrecorder/project/project.mjs +49 -0
  46. package/esm2022/lib/speechrecorder/project/project.service.mjs +64 -0
  47. package/{esm2020 → esm2022}/lib/speechrecorder/recording.mjs +123 -123
  48. package/esm2022/lib/speechrecorder/recordings/basic_recording.service.mjs +218 -0
  49. package/esm2022/lib/speechrecorder/recordings/recordings.service.mjs +1014 -0
  50. package/{esm2020 → esm2022}/lib/speechrecorder/script/script.mjs +114 -114
  51. package/{esm2020 → esm2022}/lib/speechrecorder/script/script.service.mjs +47 -47
  52. package/esm2022/lib/speechrecorder/session/audiorecorder.mjs +1179 -0
  53. package/esm2022/lib/speechrecorder/session/basicrecorder.mjs +668 -0
  54. package/esm2022/lib/speechrecorder/session/controlpanel.mjs +416 -0
  55. package/{esm2020 → esm2022}/lib/speechrecorder/session/item.mjs +29 -29
  56. package/{esm2020 → esm2022}/lib/speechrecorder/session/progress.mjs +69 -69
  57. package/{esm2020 → esm2022}/lib/speechrecorder/session/prompting.mjs +571 -571
  58. package/{esm2020 → esm2022}/lib/speechrecorder/session/recorder_combi_pane.mjs +65 -65
  59. package/esm2022/lib/speechrecorder/session/recording_file_cache.mjs +195 -0
  60. package/{esm2020 → esm2022}/lib/speechrecorder/session/recording_list.mjs +103 -103
  61. package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-meta.component.mjs +63 -63
  62. package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-navi.component.mjs +51 -51
  63. package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.mjs +104 -104
  64. package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-view.component.mjs +381 -381
  65. package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file.mjs +67 -67
  66. package/esm2022/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +288 -0
  67. package/{esm2020 → esm2022}/lib/speechrecorder/session/session.mjs +1 -1
  68. package/esm2022/lib/speechrecorder/session/session.service.mjs +69 -0
  69. package/{esm2020 → esm2022}/lib/speechrecorder/session/session_finished_dialog.mjs +29 -29
  70. package/esm2022/lib/speechrecorder/session/sessionmanager.mjs +1386 -0
  71. package/{esm2020 → esm2022}/lib/speechrecorder/session/warning_bar.mjs +28 -28
  72. package/{esm2020 → esm2022}/lib/speechrecorder/spruploader.mjs +22 -22
  73. package/{esm2020 → esm2022}/lib/speechrecorder/startstopsignal/startstopsignal.mjs +1 -1
  74. package/esm2022/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.mjs +57 -0
  75. package/{esm2020 → esm2022}/lib/speechrecorderng.component.mjs +388 -388
  76. package/{esm2020 → esm2022}/lib/speechrecorderng.module.mjs +100 -100
  77. package/{esm2020 → esm2022}/lib/spr.config.mjs +26 -26
  78. package/{esm2020 → esm2022}/lib/spr.module.version.mjs +2 -2
  79. package/{esm2020 → esm2022}/lib/ui/canvas_layer_comp.mjs +38 -38
  80. package/{esm2020 → esm2022}/lib/ui/message_dialog.mjs +30 -30
  81. package/esm2022/lib/ui/recordingitem_display.mjs +253 -0
  82. package/{esm2020 → esm2022}/lib/ui/responsive_component.mjs +24 -24
  83. package/{esm2020 → esm2022}/lib/utils/scrollIntoViewToBottom.mjs +23 -23
  84. package/esm2022/lib/utils/ua-parser.mjs +190 -0
  85. package/esm2022/lib/utils/utils.mjs +105 -0
  86. package/esm2022/lib/utils/wake_lock.mjs +114 -0
  87. package/{esm2020 → esm2022}/lib/utils/wake_lock_media.mjs +1 -1
  88. package/{esm2020 → esm2022}/public-api.mjs +33 -33
  89. package/{esm2020 → esm2022}/speechrecorderng.mjs +4 -4
  90. package/{fesm2020 → fesm2022}/speechrecorderng.mjs +16518 -16454
  91. package/fesm2022/speechrecorderng.mjs.map +1 -0
  92. package/index.d.ts +5 -5
  93. package/lib/action/action.d.ts +27 -27
  94. package/lib/audio/array_audio_buffer.d.ts +31 -31
  95. package/lib/audio/array_audio_buffer_input_stream.d.ts +14 -14
  96. package/lib/audio/array_audio_buffer_random_access_stream.d.ts +9 -9
  97. package/lib/audio/audio_data_holder.d.ts +84 -84
  98. package/lib/audio/audio_display.d.ts +36 -36
  99. package/lib/audio/audio_player.d.ts +47 -47
  100. package/lib/audio/capture/capture.d.ts +67 -67
  101. package/lib/audio/context.d.ts +6 -6
  102. package/lib/audio/dsp/level_measure.d.ts +60 -60
  103. package/lib/audio/format.d.ts +11 -11
  104. package/lib/audio/impl/wavformat.d.ts +5 -5
  105. package/lib/audio/impl/wavreader.d.ts +16 -16
  106. package/lib/audio/impl/wavwriter.d.ts +13 -13
  107. package/lib/audio/inddb_audio_buffer.d.ts +68 -68
  108. package/lib/audio/io/stream.d.ts +28 -28
  109. package/lib/audio/net_audio_buffer.d.ts +57 -57
  110. package/lib/audio/persistor.d.ts +29 -29
  111. package/lib/audio/playback/array_audio_buffer_source_node.d.ts +18 -18
  112. package/lib/audio/playback/audio_source_node.d.ts +10 -10
  113. package/lib/audio/playback/audio_source_worklet_module_loader.d.ts +4 -4
  114. package/lib/audio/playback/inddb_audio_buffer_source_node.d.ts +21 -21
  115. package/lib/audio/playback/net_audio_buffer_source_node.d.ts +27 -27
  116. package/lib/audio/playback/player.d.ts +65 -65
  117. package/lib/audio/ui/audio_canvas_layer_comp.d.ts +68 -68
  118. package/lib/audio/ui/audio_display_control.d.ts +25 -25
  119. package/lib/audio/ui/audio_display_scroll_pane.d.ts +26 -26
  120. package/lib/audio/ui/audiosignal.d.ts +30 -30
  121. package/lib/audio/ui/common.d.ts +11 -11
  122. package/lib/audio/ui/container.d.ts +63 -63
  123. package/lib/audio/ui/livelevel.d.ts +60 -60
  124. package/lib/audio/ui/scroll_pane_horizontal.d.ts +5 -5
  125. package/lib/audio/ui/sonagram.d.ts +37 -37
  126. package/lib/db/inddb.d.ts +21 -21
  127. package/lib/dsp/utils.d.ts +19 -19
  128. package/lib/io/BinaryReader.d.ts +18 -18
  129. package/lib/io/BinaryWriter.d.ts +15 -15
  130. package/lib/io/stream.d.ts +59 -59
  131. package/lib/math/2d/geometry.d.ts +18 -18
  132. package/lib/math/complex.d.ts +17 -17
  133. package/lib/math/dft.d.ts +22 -22
  134. package/lib/media/utils.d.ts +3 -3
  135. package/lib/net/uploader.d.ts +81 -81
  136. package/lib/recorder_component.d.ts +16 -16
  137. package/lib/speechrecorder/project/project.d.ts +59 -59
  138. package/lib/speechrecorder/project/project.service.d.ts +21 -21
  139. package/lib/speechrecorder/recording.d.ts +51 -51
  140. package/lib/speechrecorder/recordings/basic_recording.service.d.ts +27 -27
  141. package/lib/speechrecorder/recordings/recordings.service.d.ts +48 -48
  142. package/lib/speechrecorder/script/script.d.ts +80 -79
  143. package/lib/speechrecorder/script/script.service.d.ts +16 -16
  144. package/lib/speechrecorder/session/audiorecorder.d.ts +122 -122
  145. package/lib/speechrecorder/session/basicrecorder.d.ts +139 -139
  146. package/lib/speechrecorder/session/controlpanel.d.ts +109 -107
  147. package/lib/speechrecorder/session/item.d.ts +12 -12
  148. package/lib/speechrecorder/session/progress.d.ts +17 -17
  149. package/lib/speechrecorder/session/prompting.d.ts +121 -121
  150. package/lib/speechrecorder/session/recorder_combi_pane.d.ts +32 -32
  151. package/lib/speechrecorder/session/recording_file_cache.d.ts +33 -33
  152. package/lib/speechrecorder/session/recording_list.d.ts +24 -24
  153. package/lib/speechrecorder/session/recordingfile/recording-file-meta.component.d.ts +15 -15
  154. package/lib/speechrecorder/session/recordingfile/recording-file-navi.component.d.ts +20 -20
  155. package/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.d.ts +31 -31
  156. package/lib/speechrecorder/session/recordingfile/recording-file-view.component.d.ts +55 -55
  157. package/lib/speechrecorder/session/recordingfile/recording-file.d.ts +7 -7
  158. package/lib/speechrecorder/session/recordingfile/recordingfile-service.d.ts +24 -24
  159. package/lib/speechrecorder/session/session.d.ts +15 -15
  160. package/lib/speechrecorder/session/session.service.d.ts +20 -20
  161. package/lib/speechrecorder/session/session_finished_dialog.d.ts +10 -10
  162. package/lib/speechrecorder/session/sessionmanager.d.ts +129 -123
  163. package/lib/speechrecorder/session/warning_bar.d.ts +8 -8
  164. package/lib/speechrecorder/spruploader.d.ts +11 -11
  165. package/lib/speechrecorder/startstopsignal/startstopsignal.d.ts +10 -10
  166. package/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.d.ts +11 -11
  167. package/lib/speechrecorderng.component.d.ts +61 -61
  168. package/lib/speechrecorderng.module.d.ts +56 -56
  169. package/lib/spr.config.d.ts +17 -17
  170. package/lib/spr.module.version.d.ts +1 -1
  171. package/lib/ui/canvas_layer_comp.d.ts +13 -13
  172. package/lib/ui/message_dialog.d.ts +10 -10
  173. package/lib/ui/recordingitem_display.d.ts +84 -84
  174. package/lib/ui/responsive_component.d.ts +9 -9
  175. package/lib/utils/scrollIntoViewToBottom.d.ts +9 -9
  176. package/lib/utils/ua-parser.d.ts +43 -43
  177. package/lib/utils/utils.d.ts +19 -19
  178. package/lib/utils/wake_lock.d.ts +23 -23
  179. package/lib/utils/wake_lock_media.d.ts +1 -1
  180. package/package.json +17 -23
  181. package/public-api.d.ts +33 -33
  182. package/esm2020/lib/action/action.mjs +0 -73
  183. package/esm2020/lib/audio/audio_data_holder.mjs +0 -264
  184. package/esm2020/lib/audio/capture/capture.mjs +0 -855
  185. package/esm2020/lib/audio/context.mjs +0 -79
  186. package/esm2020/lib/audio/impl/wavformat.mjs +0 -6
  187. package/esm2020/lib/audio/impl/wavwriter.mjs +0 -105
  188. package/esm2020/lib/audio/inddb_audio_buffer.mjs +0 -508
  189. package/esm2020/lib/audio/net_audio_buffer.mjs +0 -293
  190. package/esm2020/lib/audio/playback/audio_source_node.mjs +0 -18
  191. package/esm2020/lib/audio/playback/audio_source_worklet_module_loader.mjs +0 -167
  192. package/esm2020/lib/audio/playback/player.mjs +0 -402
  193. package/esm2020/lib/audio/ui/audio_canvas_layer_comp.mjs +0 -347
  194. package/esm2020/lib/audio/ui/container.mjs +0 -414
  195. package/esm2020/lib/audio/ui/scroll_pane_horizontal.mjs +0 -11
  196. package/esm2020/lib/audio/ui/sonagram.mjs +0 -900
  197. package/esm2020/lib/db/inddb.mjs +0 -120
  198. package/esm2020/lib/dsp/utils.mjs +0 -48
  199. package/esm2020/lib/io/BinaryWriter.mjs +0 -74
  200. package/esm2020/lib/math/complex.mjs +0 -58
  201. package/esm2020/lib/net/uploader.mjs +0 -367
  202. package/esm2020/lib/speechrecorder/project/project.mjs +0 -49
  203. package/esm2020/lib/speechrecorder/project/project.service.mjs +0 -64
  204. package/esm2020/lib/speechrecorder/recordings/basic_recording.service.mjs +0 -216
  205. package/esm2020/lib/speechrecorder/recordings/recordings.service.mjs +0 -1014
  206. package/esm2020/lib/speechrecorder/session/audiorecorder.mjs +0 -1179
  207. package/esm2020/lib/speechrecorder/session/basicrecorder.mjs +0 -666
  208. package/esm2020/lib/speechrecorder/session/controlpanel.mjs +0 -409
  209. package/esm2020/lib/speechrecorder/session/recording_file_cache.mjs +0 -195
  210. package/esm2020/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +0 -288
  211. package/esm2020/lib/speechrecorder/session/session.service.mjs +0 -69
  212. package/esm2020/lib/speechrecorder/session/sessionmanager.mjs +0 -1333
  213. package/esm2020/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.mjs +0 -57
  214. package/esm2020/lib/ui/recordingitem_display.mjs +0 -253
  215. package/esm2020/lib/utils/ua-parser.mjs +0 -190
  216. package/esm2020/lib/utils/utils.mjs +0 -105
  217. package/esm2020/lib/utils/wake_lock.mjs +0 -114
  218. package/fesm2015/speechrecorderng.mjs +0 -17708
  219. package/fesm2015/speechrecorderng.mjs.map +0 -1
  220. package/fesm2020/speechrecorderng.mjs.map +0 -1
@@ -1,666 +0,0 @@
1
- import { __decorate, __param } from "tslib";
2
- import { TransportActions } from "./controlpanel";
3
- import { Browser, UserAgentBuilder } from "../../utils/ua-parser";
4
- import { MessageDialog } from "../../ui/message_dialog";
5
- import { SessionService } from "./session.service";
6
- import { AudioStorageType } from "../project/project";
7
- import { LevelMeasure, StreamLevelMeasure } from "../../audio/dsp/level_measure";
8
- import { Action } from "../../action/action";
9
- import { MIN_DB_LEVEL } from "../../ui/recordingitem_display";
10
- import { Upload, UploadSet } from "../../net/uploader";
11
- import { Inject } from "@angular/core";
12
- import { SPEECHRECORDER_CONFIG } from "../../spr.config";
13
- import { SequenceAudioFloat32ChunkerOutStream, SequenceAudioFloat32OutStreamMultiplier } from "../../audio/io/stream";
14
- import { AudioContextProvider } from "../../audio/context";
15
- import { UUID } from "../../utils/utils";
16
- import { WakeLockManager } from "../../utils/wake_lock";
17
- import { State as LiveLevelState } from "../../audio/ui/livelevel";
18
- import { ResponsiveComponent } from "../../ui/responsive_component";
19
- export const FORCE_REQUEST_AUDIO_PERMISSIONS = false;
20
- export const RECFILE_API_CTX = 'recfile';
21
- export const MAX_RECORDING_TIME_MS = 1000 * 60 * 60 * 60; // 1 hour
22
- export const LEVEL_BAR_INTERVALL_SECONDS = 0.1; // 100ms
23
- export const NOSLEEP_VIDEO_TITLE = 'No Sleep';
24
- export class ChunkManager {
25
- constructor(chunkAudioBufferReceiver) {
26
- this.chunkAudioBufferReceiver = chunkAudioBufferReceiver;
27
- this.channels = 0;
28
- this.sampleRate = -1;
29
- this.chunkIdx = 0;
30
- }
31
- set recordingFile(value) {
32
- this._rf = value;
33
- }
34
- close() {
35
- // Nothing to do
36
- }
37
- flush() {
38
- this.chunkAudioBufferReceiver.postAudioStreamEnd(this.chunkIdx);
39
- }
40
- nextStream() {
41
- // reset chunk counter
42
- this.chunkIdx = 0;
43
- this.chunkAudioBufferReceiver.postAudioStreamStart();
44
- }
45
- setFormat(channels, sampleRate) {
46
- this.channels = channels;
47
- this.sampleRate = sampleRate;
48
- }
49
- write(buffers) {
50
- let aCtx = AudioContextProvider.audioContextInstance();
51
- let bChs = buffers.length;
52
- let frameLen = 0;
53
- if (aCtx && bChs > 0) {
54
- frameLen = buffers[0].length;
55
- try {
56
- let ad = aCtx.createBuffer(this.channels, frameLen, this.sampleRate);
57
- for (let ch = 0; ch < this.channels; ch++) {
58
- ad.copyToChannel(buffers[ch], ch);
59
- }
60
- this.chunkAudioBufferReceiver.postChunkAudioBuffer(ad, this.chunkIdx);
61
- this.chunkIdx++;
62
- }
63
- catch (err) {
64
- // TODO Handle errors
65
- // iOS Safari sometimes throws NotSupportedError
66
- console.error("Could not create audio buffer for chunked upload.");
67
- console.error("Nr. of chs: " + this.channels + ", frame length: " + frameLen + ", sample rate: " + this.sampleRate);
68
- if (err instanceof DOMException) {
69
- console.error("DOM exception: Name: " + err.name + ", Msg: " + err.message);
70
- if (err.name === 'NotSupportedError') {
71
- if (frameLen == 0) {
72
- // Empty buffers are not supported by Chromium
73
- // No data to transfer, but this case should never happen
74
- return frameLen;
75
- }
76
- else {
77
- throw err;
78
- }
79
- }
80
- else if (err.name === 'RangeError') {
81
- console.error("DOM RangeError");
82
- // Out of memory
83
- // TODO What to do ??
84
- throw err;
85
- }
86
- else {
87
- console.error("DOM Exception unknown");
88
- throw err;
89
- }
90
- }
91
- else if (err instanceof RangeError) {
92
- console.error("RangeError: Name: " + err.name + ", Msg: " + err.message);
93
- // Out of memory
94
- // TODO What to do ??
95
- throw err;
96
- }
97
- else {
98
- throw err;
99
- }
100
- }
101
- }
102
- return frameLen;
103
- }
104
- }
105
- let BasicRecorder = class BasicRecorder extends ResponsiveComponent {
106
- constructor(bpo, changeDetectorRef, dialog, sessionService, uploader, config) {
107
- super(bpo);
108
- this.bpo = bpo;
109
- this.changeDetectorRef = changeDetectorRef;
110
- this.dialog = dialog;
111
- this.sessionService = sessionService;
112
- this.uploader = uploader;
113
- this.config = config;
114
- this.maxRecTimerId = null;
115
- this.maxRecTimerRunning = false;
116
- this._maxAutoNetMemStoreSamples = BasicRecorder.DEFAULT_MAX_NET_AUTO_MEM_STORE_SAMPLES;
117
- this.statusMsg = '';
118
- this.statusWaiting = false;
119
- this.readonly = false;
120
- this.rfUuid = null;
121
- this.processingRecording = false;
122
- this.ac = null;
123
- this._wakeLock = false;
124
- this._selectedDeviceId = undefined;
125
- this._channelCount = 2;
126
- this._allowEchoCancellation = false;
127
- this._session = null;
128
- this._recordingFile = null;
129
- this.startedDate = null;
130
- this.uploadProgress = 100;
131
- this.uploadStatus = 'ok';
132
- this.uploadSet = null;
133
- this.audioSignalCollapsed = true;
134
- this.peakLevelInDb = MIN_DB_LEVEL;
135
- this.audioLoaded = false;
136
- this.disableAudioDetails = false;
137
- this._controlAudioPlayer = null;
138
- this.displayAudioClip = null;
139
- this.audioFetchSubscription = null;
140
- this.liveLevelDisplayState = LiveLevelState.READY;
141
- this.keepLiveLevel = false;
142
- this.calcBufferInfosSubscr = null;
143
- this.destroyed = false;
144
- this.navigationDisabled = true;
145
- this._uploadChunkSizeSeconds = null;
146
- //=BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS;
147
- // Default: Continuous HTML5 Audio API AudioBuffer, no chunked upload
148
- this._clientAudioStorageType = AudioStorageType.MEM_ENTIRE;
149
- this._persistentAudioStorageTarget = null;
150
- this._screenLocked = false;
151
- this.userAgent = UserAgentBuilder.userAgent();
152
- const detPfm = this.userAgent.detectedPlatform;
153
- if (detPfm) {
154
- console.debug("Detected platform: " + detPfm);
155
- }
156
- const detBr = this.userAgent.detectedBrowser;
157
- const detBrVers = this.userAgent.detectedBrowserVersion;
158
- if (detBr) {
159
- let detBrVersStr = (detBrVers) ? ' ' + detBrVers : '';
160
- console.debug("Detected browser: " + detBr + detBrVersStr);
161
- }
162
- this.transportActions = new TransportActions();
163
- this.playStartAction = new Action('Play');
164
- this.levelMeasure = new LevelMeasure();
165
- this.streamLevelMeasure = new StreamLevelMeasure();
166
- this.selCaptureDeviceId = null;
167
- }
168
- get allowEchoCancellation() {
169
- return this._allowEchoCancellation;
170
- }
171
- set allowEchoCancellation(value) {
172
- this._allowEchoCancellation = value;
173
- }
174
- get maxAutoNetMemStoreSamples() {
175
- return this._maxAutoNetMemStoreSamples;
176
- }
177
- set maxAutoNetMemStoreSamples(value) {
178
- this._maxAutoNetMemStoreSamples = value;
179
- }
180
- get clientAudioStorageType() {
181
- return this._clientAudioStorageType;
182
- }
183
- set clientAudioStorageType(value) {
184
- let oldValue = this._clientAudioStorageType;
185
- this._clientAudioStorageType = value;
186
- if (value !== oldValue) {
187
- this.configureStreamCaptureStream();
188
- }
189
- }
190
- get persistentAudioStorageTarget() {
191
- return this._persistentAudioStorageTarget;
192
- }
193
- set persistentAudioStorageTarget(value) {
194
- let oldValue = this._persistentAudioStorageTarget;
195
- this._persistentAudioStorageTarget = value;
196
- if (value !== oldValue) {
197
- this.configureStreamCaptureStream();
198
- }
199
- }
200
- get uploadChunkSizeSeconds() {
201
- return this._uploadChunkSizeSeconds;
202
- }
203
- set uploadChunkSizeSeconds(value) {
204
- let oldValue = this.uploadChunkSizeSeconds;
205
- this._uploadChunkSizeSeconds = value;
206
- if (value !== oldValue) {
207
- this.configureStreamCaptureStream();
208
- }
209
- }
210
- get wakeLock() {
211
- return this._wakeLock;
212
- }
213
- set wakeLock(value) {
214
- this._wakeLock = value;
215
- }
216
- enableWakeLockCond() {
217
- if (this.wakeLock === true) {
218
- if (!this.wakeLockManager) {
219
- this.wakeLockManager = new WakeLockManager();
220
- this.wakeLockManager.behaviorSubject.subscribe({
221
- next: (v) => {
222
- this._screenLocked = v;
223
- },
224
- error: (err) => {
225
- console.error("Wake lock error!");
226
- this._screenLocked = false;
227
- }
228
- });
229
- }
230
- this.wakeLockManager.enableWakeLock();
231
- }
232
- }
233
- disableWakeLockCond() {
234
- this.wakeLockManager?.disableWakeLock();
235
- }
236
- get screenLocked() {
237
- return this._screenLocked;
238
- }
239
- set audioDevices(audioDevices) {
240
- this._audioDevices = audioDevices;
241
- }
242
- set autoGainControlConfigs(autoGainControlConfigs) {
243
- this._autoGainControlConfigs = autoGainControlConfigs;
244
- }
245
- set channelCount(channelCount) {
246
- this._channelCount = channelCount;
247
- }
248
- set session(session) {
249
- this._session = session;
250
- }
251
- get session() {
252
- return this._session;
253
- }
254
- enableStartUserGesture() {
255
- this.statusAlertType = 'info';
256
- this.statusMsg = 'Ready.';
257
- }
258
- configureStreamCaptureStream() {
259
- let outStream;
260
- if (AudioStorageType.MEM_ENTIRE !== this._clientAudioStorageType || this.uploadChunkSizeSeconds) {
261
- if (!this.uploadChunkSizeSeconds) {
262
- this.uploadChunkSizeSeconds = BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS;
263
- }
264
- // Multiply the capture stream to...
265
- let sasm = new SequenceAudioFloat32OutStreamMultiplier();
266
- // ...upload audio data in chunks...
267
- let chMng = new ChunkManager(this); // The chunk manager connects the chunked audio stream to this class to upload the chunks
268
- let chOsUpload = new SequenceAudioFloat32ChunkerOutStream(chMng, this.uploadChunkSizeSeconds); // The audio stream chunker itself
269
- sasm.sequenceAudioFloat32OutStreams.push(chOsUpload);
270
- // ...and to measure the level
271
- let chOsLvlMeas = new SequenceAudioFloat32ChunkerOutStream(this.streamLevelMeasure, LEVEL_BAR_INTERVALL_SECONDS);
272
- sasm.sequenceAudioFloat32OutStreams.push(chOsLvlMeas);
273
- outStream = sasm;
274
- }
275
- else {
276
- outStream = new SequenceAudioFloat32ChunkerOutStream(this.streamLevelMeasure, LEVEL_BAR_INTERVALL_SECONDS);
277
- }
278
- if (this.ac) {
279
- this.ac.maxAutoNetMemStoreSamples = this._maxAutoNetMemStoreSamples;
280
- this.ac.audioStorageType = this._clientAudioStorageType;
281
- this.ac.audioOutStream = outStream;
282
- if (AudioStorageType.DB_CHUNKED === this._clientAudioStorageType && this._persistentAudioStorageTarget !== null) {
283
- this.ac.persistentAudioStorageTarget = this._persistentAudioStorageTarget;
284
- }
285
- }
286
- }
287
- showRecording() {
288
- if (this._controlAudioPlayer) {
289
- this._controlAudioPlayer.stop();
290
- }
291
- if (this.calcBufferInfosSubscr) {
292
- this.calcBufferInfosSubscr.unsubscribe();
293
- }
294
- if (this.displayAudioClip) {
295
- let dap = this.displayAudioClip;
296
- let adh = dap.audioDataHolder;
297
- if (adh) {
298
- if (!this.keepLiveLevel) {
299
- this.liveLevelDisplayState = LiveLevelState.LOADING;
300
- }
301
- adh.addOnReadyListener(() => {
302
- //console.debug("Audio data holder ready. Enable playback. Audio loaded true.")
303
- if (!this.keepLiveLevel) {
304
- this.liveLevelDisplayState = LiveLevelState.RENDERING;
305
- this.calcBufferInfosSubscr = this.levelMeasure.calcBufferLevelInfos(adh, LEVEL_BAR_INTERVALL_SECONDS).subscribe((levelInfos) => {
306
- //console.debug("Level infos: levelInfos number size: "+levelInfos.numberSize());
307
- dap.levelInfos = levelInfos;
308
- this.liveLevelDisplayState = LiveLevelState.READY;
309
- this.changeDetectorRef.detectChanges();
310
- });
311
- }
312
- this.playStartAction.disabled = false;
313
- this.audioLoaded = true;
314
- this.changeDetectorRef.detectChanges();
315
- });
316
- //console.debug("Audio data holder added onReady.")
317
- }
318
- //this.playStartAction.disabled = false;
319
- }
320
- else {
321
- this.playStartAction.disabled = true;
322
- this.audioLoaded = false;
323
- // Collapse audio signal display if open
324
- if (!this.audioSignalCollapsed) {
325
- this.audioSignalCollapsed = true;
326
- }
327
- }
328
- this.changeDetectorRef.detectChanges();
329
- }
330
- start() {
331
- this.statusAlertType = 'info';
332
- this.statusMsg = 'Starting session...';
333
- this.statusWaiting = false;
334
- if (this._session) {
335
- if (this._session.sealed) {
336
- this.readonly = true;
337
- this.statusMsg = 'Session sealed!';
338
- //let dialogRef = this.dialog.open(SessionSealedDialog, {});
339
- this.dialog.open(MessageDialog, {
340
- data: {
341
- type: 'error',
342
- title: 'Error',
343
- msg: "This session is sealed. Recordings cannot be added anymore.",
344
- advice: 'Please ask your experimenter what to do (e.g start a new session).',
345
- }
346
- });
347
- }
348
- else {
349
- let body = {};
350
- if (this._session.status === "CREATED") {
351
- this._session.status = "LOADED";
352
- body.status = this._session.status;
353
- if (!this._session.loadedDate) {
354
- this._session.loadedDate = new Date();
355
- body.loadedDate = this._session.loadedDate;
356
- }
357
- }
358
- else {
359
- this._session.restartedDate = new Date();
360
- body.restartedDate = this._session.restartedDate;
361
- }
362
- this.sessionService.patchSessionObserver(this._session, body).subscribe();
363
- }
364
- }
365
- // Check browser compatibility
366
- if (this.userAgent.detectedBrowser === Browser.Safari && this._channelCount > 1) {
367
- let eMsg = "Error: Safari browser does not support stereo recordings.";
368
- console.error(eMsg);
369
- this.dialog.open(MessageDialog, {
370
- data: {
371
- type: 'error',
372
- title: 'Browser not supported',
373
- msg: eMsg,
374
- advice: "Please use a supported browser, e.g. Mozilla Firefox."
375
- }
376
- });
377
- }
378
- //console.log("Session ID: "+this._session.session+ " status: "+this._session.status)
379
- this._selectedDeviceId = undefined;
380
- if (!this.readonly && this.ac && (FORCE_REQUEST_AUDIO_PERMISSIONS || (this._audioDevices && this._audioDevices.length > 0))) {
381
- this.statusMsg = 'Requesting audio permissions...';
382
- this.statusAlertType = 'info';
383
- this.ac.deviceInfos((mdis) => {
384
- let audioCaptureDeviceAvail = false;
385
- let audioPlayDeviceAvail = false;
386
- if (mdis) {
387
- if (this.ac) {
388
- this.ac.printDevices(mdis);
389
- }
390
- if (mdis.length > 0) {
391
- for (let mdii = 0; mdii < mdis.length; mdii++) {
392
- let mdi = mdis[mdii];
393
- let kind = mdi.kind;
394
- if (kind === "audioinput") {
395
- audioCaptureDeviceAvail = true;
396
- }
397
- else if (kind === "audiooutput") {
398
- audioPlayDeviceAvail = true;
399
- }
400
- }
401
- }
402
- if (this._session && this._session.type !== 'TEST_DEF_A' && this._audioDevices && this._audioDevices.length > 0) {
403
- let fdi = null;
404
- for (let adI = 0; adI < this._audioDevices.length; adI++) {
405
- let ad = this._audioDevices[adI];
406
- if (ad.playback) {
407
- // project audio device config for playback device
408
- // not used for now
409
- continue;
410
- }
411
- for (let mdii = 0; mdii < mdis.length; mdii++) {
412
- let mdi = mdis[mdii];
413
- let kind = mdi.kind;
414
- if (kind === "audioinput") {
415
- audioCaptureDeviceAvail = true;
416
- }
417
- else if (kind === "audiooutput") {
418
- audioPlayDeviceAvail = true;
419
- }
420
- if (ad.regex) {
421
- //console.log("Match?: \'"+mdi.label+"\' \'"+ad.name+"\'");
422
- if (mdi.label.match(ad.name)) {
423
- fdi = mdi;
424
- //console.log("Match!");
425
- }
426
- }
427
- else {
428
- if (mdi.label.trim() === ad.name.trim()) {
429
- fdi = mdi;
430
- }
431
- }
432
- if (fdi) {
433
- break;
434
- }
435
- }
436
- if (fdi) {
437
- break;
438
- }
439
- }
440
- if (fdi) {
441
- // matching device found
442
- // Not able to open device here since Chrome 71
443
- // Chrome 71 requires a user gesture before the AudioContext can be resumed
444
- // sessionmanager.ts:712 Open session with default audio device for 1 channels
445
- // capture.ts:128 The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://goo.gl/7K7WLu
446
- // push../projects/speechrecorderng/src/lib/audio/capture/capture.ts.AudioCapture.open @ capture.ts:128
447
- //this.ac.open(this._channelCount, fdi.deviceId);
448
- console.info("Set selected audio device: \'" + fdi.label + "\' Id: \'" + fdi.deviceId + "\'");
449
- this._selectedDeviceId = fdi.deviceId;
450
- this.enableStartUserGesture();
451
- }
452
- else {
453
- // device not found
454
- this.statusMsg = 'ERROR: Required audio device not available!';
455
- this.statusAlertType = 'error';
456
- this.readonly = true;
457
- this.dialog.open(MessageDialog, {
458
- data: {
459
- type: 'error',
460
- title: 'Required audio device',
461
- msg: "Required audio device not found",
462
- advice: "Please connect a suitable audio device for this project and retry (press the browser reload button)."
463
- }
464
- });
465
- }
466
- }
467
- else {
468
- if (!audioCaptureDeviceAvail && !audioPlayDeviceAvail) {
469
- // no device found
470
- this.statusMsg = 'ERROR: No audio device available!';
471
- this.statusAlertType = 'warn';
472
- //this.readonly = true;
473
- this.dialog.open(MessageDialog, {
474
- data: {
475
- type: 'warn',
476
- title: 'No audio device',
477
- msg: "No audio device found",
478
- advice: "Please connect an audio device and retry (press the browser reload button) or try to continue anyway."
479
- }
480
- });
481
- }
482
- else {
483
- if (!this.readonly && !audioCaptureDeviceAvail) {
484
- // no device found
485
- this.statusMsg = 'WARNING: No audio capture device available!';
486
- this.statusAlertType = 'warning';
487
- //this.readonly = true;
488
- this.dialog.open(MessageDialog, {
489
- data: {
490
- type: 'warning',
491
- title: 'No audio capture device',
492
- msg: "No audio capture device found",
493
- advice: "Please connect an audio capture device and retry (press the browser reload button) or try to continue anyway."
494
- }
495
- });
496
- }
497
- // Safari does not list playback devices
498
- if (!audioPlayDeviceAvail) {
499
- // Firefox does not enumerate audiooutput devices
500
- // Do not show this warning, because it would always appear on Firefox
501
- // When https://bugzilla.mozilla.org/show_bug.cgi?id=1498512 is fixed the warning can be enabled for Firefox as well
502
- // It is already implemneted but kept behind a preference setting https://bugzilla.mozilla.org/show_bug.cgi?id=1152401
503
- // Output devices are listed if about:config media.setsinkid.enabled=true
504
- // but default setting is false
505
- // Same problem with Safari
506
- if (!(this.userAgent.detectedBrowser === Browser.Safari || this.userAgent.detectedBrowser === Browser.Firefox)) {
507
- // no device found
508
- this.statusMsg = 'WARNING: No audio playback device available!';
509
- this.statusAlertType = 'warn';
510
- //this.readonly = true;
511
- this.dialog.open(MessageDialog, {
512
- data: {
513
- type: 'warn',
514
- title: 'No audio playback device',
515
- msg: "No audio playback device found",
516
- advice: "Please connect an audio playback device and retry (press the browser reload button) or try to continue anyway."
517
- }
518
- });
519
- }
520
- }
521
- }
522
- // Not able to open device here since Chrome 71
523
- // Chrome 71 requires a user gesture before the AudioContext can be resumed
524
- // sessionmanager.ts:712 Open session with default audio device for 1 channels
525
- // capture.ts:128 The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://goo.gl/7K7WLu
526
- // push../projects/speechrecorderng/src/lib/audio/capture/capture.ts.AudioCapture.open @ capture.ts:128
527
- //console.log("Open session with default audio device for "+this._channelCount+" channels");
528
- //this.ac.open(this._channelCount);
529
- // enable start gesture anyway
530
- this.enableStartUserGesture();
531
- }
532
- }
533
- });
534
- }
535
- this.statusMsg = 'Ready.';
536
- }
537
- startItem() {
538
- this.rfUuid = UUID.generate();
539
- if (this.ac) {
540
- this.ac.recUUID = this.rfUuid;
541
- }
542
- this.startedDate = null;
543
- this.enableWakeLockCond();
544
- //this.rfUuid=UUID.generate();
545
- this.uploadSet = null;
546
- this.transportActions.startAction.disabled = true;
547
- this.transportActions.pauseAction.disabled = true;
548
- }
549
- startCapture() {
550
- if (this.ac) {
551
- if (!this.ac.opened) {
552
- if (this._selectedDeviceId) {
553
- console.log("Open session with audio device Id: \'" + this._selectedDeviceId + "\' for " + this._channelCount + " channels");
554
- }
555
- else {
556
- console.log("Open session with default audio device for " + this._channelCount + " channels");
557
- }
558
- this.ac.open(this._channelCount, this._selectedDeviceId, this._autoGainControlConfigs, this._allowEchoCancellation);
559
- }
560
- else {
561
- this.ac.start();
562
- }
563
- }
564
- }
565
- opened() {
566
- if (this.ac) {
567
- this.ac.start();
568
- }
569
- }
570
- started() {
571
- if (!this.startedDate) {
572
- this.startedDate = new Date();
573
- }
574
- this.transportActions.startAction.disabled = true;
575
- }
576
- postRecording(wavFile, recUrl, rf, uploadHolder) {
577
- let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
578
- let ul = new Upload(wavBlob, recUrl, rf);
579
- if (uploadHolder) {
580
- uploadHolder.upload = ul;
581
- }
582
- this.uploader.queueUpload(ul);
583
- }
584
- postAudioStreamStart() {
585
- if (this.rfUuid) {
586
- this.uploadSet = new UploadSet();
587
- let apiEndPoint = '';
588
- if (this.config && this.config.apiEndPoint) {
589
- apiEndPoint = this.config.apiEndPoint;
590
- }
591
- if (apiEndPoint !== '') {
592
- apiEndPoint = apiEndPoint + '/';
593
- }
594
- let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
595
- let recUrl = sessionsUrl + '/' + this.session?.sessionId + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/prepareChunksRequest';
596
- let fd = new FormData();
597
- // Note: At least one parameter must be set
598
- fd.set('uuid', this.rfUuid);
599
- if (!this.startedDate) {
600
- this.startedDate = new Date();
601
- }
602
- fd.set('startedDate', this.startedDate.toJSON());
603
- let ul = new Upload(fd, recUrl);
604
- this.uploadSet.add(ul);
605
- this.uploader.queueUpload(ul);
606
- }
607
- else {
608
- console.error("Recording file UUID not set!");
609
- }
610
- }
611
- sessionsBaseUrl() {
612
- let apiEndPoint = '';
613
- if (this.config && this.config.apiEndPoint) {
614
- apiEndPoint = this.config.apiEndPoint;
615
- }
616
- if (apiEndPoint !== '') {
617
- apiEndPoint = apiEndPoint + '/';
618
- }
619
- return apiEndPoint + SessionService.SESSION_API_CTX;
620
- }
621
- postAudioStreamEnd(chunkCount) {
622
- if (this.rfUuid) {
623
- let sessionsUrl = this.sessionsBaseUrl();
624
- let recUrl = sessionsUrl + '/' + this.session?.sessionId + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/concatChunksRequest';
625
- let fd = new FormData();
626
- fd.set('uuid', this.rfUuid);
627
- fd.set('chunkCount', chunkCount.toString());
628
- let ul = new Upload(fd, recUrl, this._recordingFile);
629
- if (this.uploadSet) {
630
- this.uploadSet.add(ul);
631
- this.uploadSet.complete();
632
- }
633
- this.uploader.queueUpload(ul);
634
- //console.debug("Queued for upload: "+this._recordingFile);
635
- }
636
- else {
637
- console.error("Recording file UUID not set!");
638
- }
639
- }
640
- closed() {
641
- this.statusAlertType = 'info';
642
- this.statusMsg = 'Session closed.';
643
- }
644
- error(msg = 'An unknown error occured during recording.', advice = 'Please retry.') {
645
- this.navigationDisabled = false;
646
- this.statusMsg = 'ERROR: Recording.';
647
- this.statusAlertType = 'error';
648
- this.dialog.open(MessageDialog, {
649
- data: {
650
- type: 'error',
651
- title: 'Recording error',
652
- msg: msg,
653
- advice: advice
654
- }
655
- });
656
- }
657
- };
658
- BasicRecorder.DEFAULT_MAX_NET_AUTO_MEM_STORE_SAMPLES = 2880000 * 5; // Default 5 minutes one channel at 48kHz
659
- BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS = 30;
660
- // Enable only for developemnt/debug purposes of array audio buffers !!
661
- BasicRecorder.FORCE_ARRRAY_AUDIO_BUFFER = false;
662
- BasicRecorder = __decorate([
663
- __param(5, Inject(SPEECHRECORDER_CONFIG))
664
- ], BasicRecorder);
665
- export { BasicRecorder };
666
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzaWNyZWNvcmRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3NwZWVjaHJlY29yZGVybmcvc3JjL2xpYi9zcGVlY2hyZWNvcmRlci9zZXNzaW9uL2Jhc2ljcmVjb3JkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQ2hELE9BQU8sRUFBQyxPQUFPLEVBQWEsZ0JBQWdCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUUzRSxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0seUJBQXlCLENBQUM7QUFFdEQsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBRWpELE9BQU8sRUFBYyxnQkFBZ0IsRUFBd0IsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RixPQUFPLEVBQUMsWUFBWSxFQUFFLGtCQUFrQixFQUFDLE1BQU0sK0JBQStCLENBQUM7QUFJL0UsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBQzNDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM1RCxPQUFPLEVBQUMsTUFBTSxFQUFnQixTQUFTLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUNuRSxPQUFPLEVBQW9CLE1BQU0sRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN4RCxPQUFPLEVBQUMscUJBQXFCLEVBQXVCLE1BQU0sa0JBQWtCLENBQUM7QUFHN0UsT0FBTyxFQUNMLG9DQUFvQyxFQUVwQyx1Q0FBdUMsRUFDeEMsTUFBTSx1QkFBdUIsQ0FBQztBQUUvQixPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUN6RCxPQUFPLEVBQUMsSUFBSSxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDdkMsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBQ3RELE9BQU8s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QUUsQ0FBQzthQUMzQjtZQUNELElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzlCLDJEQUEyRDtTQUM1RDthQUFJO1lBQ0gsT0FBTyxDQUFDLEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFBO1NBQzlDO0lBQ0gsQ0FBQztJQUVELE1BQU07UUFDSixJQUFJLENBQUMsZUFBZSxHQUFHLE1BQU0sQ0FBQztRQUM5QixJQUFJLENBQUMsU0FBUyxHQUFHLGlCQUFpQixDQUFDO0lBQ3JDLENBQUM7SUFFRCxLQUFLLENBQUMsR0FBRyxHQUFDLDRDQUE0QyxFQUFDLFNBQWMsZUFBZTtRQUNsRixJQUFJLENBQUMsa0JBQWtCLEdBQUcsS0FBSyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxTQUFTLEdBQUcsbUJBQW1CLENBQUM7UUFDckMsSUFBSSxDQUFDLGVBQWUsR0FBRyxPQUFPLENBQUM7UUFDL0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFO1lBQzlCLElBQUksRUFBRTtnQkFDSixJQUFJLEVBQUUsT0FBTztnQkFDYixLQUFLLEVBQUUsaUJBQWlCO2dCQUN4QixHQUFHLEVBQUUsR0FBRztnQkFDUixNQUFNLEVBQUUsTUFBTTthQUNmO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUVGLENBQUE7QUE5bUJ3QixvREFBc0MsR0FBUSxPQUFPLEdBQUMsQ0FBRSxDQUFBLENBQUMseUNBQXlDO0FBR2xHLHdDQUEwQixHQUFRLEVBQUcsQ0FBQTtBQTJCNUQsdUVBQXVFO0FBQ2hELHVDQUF5QixHQUFDLEtBQU0sQ0FBQTtBQXJEbkMsYUFBYTtJQW9JbEIsV0FBQSxNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQTtHQXBJeEIsYUFBYSxDQW9vQmxDO1NBcG9CcUIsYUFBYSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7VHJhbnNwb3J0QWN0aW9uc30gZnJvbSBcIi4vY29udHJvbHBhbmVsXCI7XHJcbmltcG9ydCB7QnJvd3NlciwgVXNlckFnZW50LCBVc2VyQWdlbnRCdWlsZGVyfSBmcm9tIFwiLi4vLi4vdXRpbHMvdWEtcGFyc2VyXCI7XHJcbmltcG9ydCB7TWF0RGlhbG9nfSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nXCI7XHJcbmltcG9ydCB7TWVzc2FnZURpYWxvZ30gZnJvbSBcIi4uLy4uL3VpL21lc3NhZ2VfZGlhbG9nXCI7XHJcbmltcG9ydCB7U2Vzc2lvbn0gZnJvbSBcIi4vc2Vzc2lvblwiO1xyXG5pbXBvcnQge1Nlc3Npb25TZXJ2aWNlfSBmcm9tIFwiLi9zZXNzaW9uLnNlcnZpY2VcIjtcclxuaW1wb3J0IHtBdWRpb0NhcHR1cmV9IGZyb20gXCIuLi8uLi9hdWRpby9jYXB0dXJlL2NhcHR1cmVcIjtcclxuaW1wb3J0IHtBdWRpb0RldmljZSwgQXVkaW9TdG9yYWdlVHlwZSwgQXV0b0dhaW5Db250cm9sQ29uZmlnfSBmcm9tIFwiLi4vcHJvamVjdC9wcm9qZWN0XCI7XHJcbmltcG9ydCB7TGV2ZWxNZWFzdXJlLCBTdHJlYW1MZXZlbE1lYXN1cmV9IGZyb20gXCIuLi8uLi9hdWRpby9kc3AvbGV2ZWxfbWVhc3VyZVwiO1xyXG5pbXBvcnQge0F1ZGlvUGxheWVyfSBmcm9tIFwiLi4vLi4vYXVkaW8vcGxheWJhY2svcGxheWVyXCI7XHJcbmltcG9ydCB7U3Vic2NyaXB0aW9ufSBmcm9tIFwicnhqc1wiO1xyXG5pbXBvcnQge0F1ZGlvQ2xpcH0gZnJvbSBcIi4uLy4uL2F1ZGlvL3BlcnNpc3RvclwiO1xyXG5pbXBvcnQge0FjdGlvbn0gZnJvbSBcIi4uLy4uL2FjdGlvbi9hY3Rpb25cIjtcclxuaW1wb3J0IHtNSU5fREJfTEVWRUx9IGZyb20gXCIuLi8uLi91aS9yZWNvcmRpbmdpdGVtX2Rpc3BsYXlcIjtcclxuaW1wb3J0IHtVcGxvYWQsIFVwbG9hZEhvbGRlciwgVXBsb2FkU2V0fSBmcm9tIFwiLi4vLi4vbmV0L3VwbG9hZGVyXCI7XHJcbmltcG9ydCB7Q2hhbmdlRGV0ZWN0b3JSZWYsIEluamVjdH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHtTUEVFQ0hSRUNPUkRFUl9DT05GSUcsIFNwZWVjaFJlY29yZGVyQ29uZmlnfSBmcm9tIFwiLi4vLi4vc3ByLmNvbmZpZ1wiO1xyXG5pbXBvcnQge1NwZWVjaFJlY29yZGVyVXBsb2FkZXJ9IGZyb20gXCIuLi9zcHJ1cGxvYWRlclwiO1xyXG5cclxuaW1wb3J0IHtcclxuICBTZXF1ZW5jZUF1ZGlvRmxvYXQzMkNodW5rZXJPdXRTdHJlYW0sXHJcbiAgU2VxdWVuY2VBdWRpb0Zsb2F0MzJPdXRTdHJlYW0sXHJcbiAgU2VxdWVuY2VBdWRpb0Zsb2F0MzJPdXRTdHJlYW1NdWx0aXBsaWVyXHJcbn0gZnJvbSBcIi4uLy4uL2F1ZGlvL2lvL3N0cmVhbVwiO1xyXG5pbXBvcnQge1JlY29yZGluZ0ZpbGUsIFNwclJlY29yZGluZ0ZpbGV9IGZyb20gXCIuLi9yZWNvcmRpbmdcIjtcclxuaW1wb3J0IHtBdWRpb0NvbnRleHRQcm92aWRlcn0gZnJvbSBcIi4uLy4uL2F1ZGlvL2NvbnRleHRcIjtcclxuaW1wb3J0IHtVVUlEfSBmcm9tIFwiLi4vLi4vdXRpbHMvdXRpbHNcIjtcclxuaW1wb3J0IHtXYWtlTG9ja01hbmFnZXJ9IGZyb20gXCIuLi8uLi91dGlscy93YWtlX2xvY2tcIjtcclxuaW1wb3J0IHtTdGF0ZSBhcyBMaXZlTGV2ZWxTdGF0ZX0gZnJvbSBcIi4uLy4uL2F1ZGlvL3VpL2xpdmVsZXZlbFwiXHJcbmltcG9ydCB7UGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldH0gZnJvbSBcIi4uLy4uL2F1ZGlvL2luZGRiX2F1ZGlvX2J1ZmZlclwiO1xyXG5pbXBvcnQge1Jlc3BvbnNpdmVDb21wb25lbnR9IGZyb20gXCIuLi8uLi91aS9yZXNwb25zaXZlX2NvbXBvbmVudFwiO1xyXG5pbXBvcnQge0JyZWFrcG9pbnRPYnNlcnZlcn0gZnJvbSBcIkBhbmd1bGFyL2Nkay9sYXlvdXRcIjtcclxuXHJcbmV4cG9ydCBjb25zdCBGT1JDRV9SRVFVRVNUX0FVRElPX1BFUk1JU1NJT05TPWZhbHNlO1xyXG5leHBvcnQgY29uc3QgUkVDRklMRV9BUElfQ1RYID0gJ3JlY2ZpbGUnO1xyXG5leHBvcnQgY29uc3QgTUFYX1JFQ09SRElOR19USU1FX01TID0gMTAwMCAqIDYwICogNjAgKiA2MDsgLy8gMSBob3VyXHJcblxyXG5leHBvcnQgY29uc3QgTEVWRUxfQkFSX0lOVEVSVkFMTF9TRUNPTkRTID0gMC4xOyAgLy8gMTAwbXNcclxuXHJcbmV4cG9ydCBjb25zdCBOT1NMRUVQX1ZJREVPX1RJVExFPSdObyBTbGVlcCc7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIENodW5rQXVkaW9CdWZmZXJSZWNlaXZlcntcclxuICBwb3N0QXVkaW9TdHJlYW1TdGFydCgpOnZvaWQ7XHJcbiAgcG9zdENodW5rQXVkaW9CdWZmZXIoYXVkaW9CdWZmZXI6QXVkaW9CdWZmZXIsY2h1bmtJZHg6bnVtYmVyKTp2b2lkO1xyXG4gIHBvc3RBdWRpb1N0cmVhbUVuZChjaHVua0NvdW50Om51bWJlcik6dm9pZDtcclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIENodW5rTWFuYWdlciBpbXBsZW1lbnRzIFNlcXVlbmNlQXVkaW9GbG9hdDMyT3V0U3RyZWFte1xyXG5cclxuICBzZXQgcmVjb3JkaW5nRmlsZSh2YWx1ZTogU3ByUmVjb3JkaW5nRmlsZSkge1xyXG4gICAgdGhpcy5fcmYgPSB2YWx1ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2hhbm5lbHM6bnVtYmVyPTA7XHJcbiAgcHJpdmF0ZSBzYW1wbGVSYXRlOm51bWJlcj0tMTtcclxuXHJcbiAgcHJpdmF0ZSBfcmYhOlNwclJlY29yZGluZ0ZpbGU7XHJcblxyXG4gIHByaXZhdGUgY2h1bmtJZHg6bnVtYmVyPTA7XHJcblxyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNodW5rQXVkaW9CdWZmZXJSZWNlaXZlcjpDaHVua0F1ZGlvQnVmZmVyUmVjZWl2ZXIpIHtcclxuICB9XHJcblxyXG4gIGNsb3NlKCk6IHZvaWQge1xyXG4gICAgLy8gTm90aGluZyB0byBkb1xyXG4gIH1cclxuXHJcbiAgZmx1c2goKTogdm9pZCB7XHJcbiAgICB0aGlzLmNodW5rQXVkaW9CdWZmZXJSZWNlaXZlci5wb3N0QXVkaW9TdHJlYW1FbmQodGhpcy5jaHVua0lkeCk7XHJcbiAgfVxyXG5cclxuICBuZXh0U3RyZWFtKCk6IHZvaWQge1xyXG4gICAgLy8gcmVzZXQgY2h1bmsgY291bnRlclxyXG4gICAgdGhpcy5jaHVua0lkeD0wO1xyXG4gICAgdGhpcy5jaHVua0F1ZGlvQnVmZmVyUmVjZWl2ZXIucG9zdEF1ZGlvU3RyZWFtU3RhcnQoKTtcclxuICB9XHJcblxyXG4gIHNldEZvcm1hdChjaGFubmVsczogbnVtYmVyLCBzYW1wbGVSYXRlOiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMuY2hhbm5lbHM9Y2hhbm5lbHM7XHJcbiAgICB0aGlzLnNhbXBsZVJhdGU9c2FtcGxlUmF0ZTtcclxuICB9XHJcblxyXG4gIHdyaXRlKGJ1ZmZlcnM6IEFycmF5PEZsb2F0MzJBcnJheT4pOiBudW1iZXIge1xyXG4gICAgbGV0IGFDdHg9QXVkaW9Db250ZXh0UHJvdmlkZXIuYXVkaW9Db250ZXh0SW5zdGFuY2UoKTtcclxuICAgIGxldCBiQ2hzPWJ1ZmZlcnMubGVuZ3RoO1xyXG4gICAgbGV0IGZyYW1lTGVuPTA7XHJcbiAgICBpZihhQ3R4ICYmIGJDaHM+MCkge1xyXG4gICAgICBmcmFtZUxlbj1idWZmZXJzWzBdLmxlbmd0aDtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBsZXQgYWQgPSBhQ3R4LmNyZWF0ZUJ1ZmZlcih0aGlzLmNoYW5uZWxzLCBmcmFtZUxlbiwgdGhpcy5zYW1wbGVSYXRlKTtcclxuICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgdGhpcy5jaGFubmVsczsgY2grKykge1xyXG4gICAgICAgICAgYWQuY29weVRvQ2hhbm5lbChidWZmZXJzW2NoXSxjaCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuY2h1bmtBdWRpb0J1ZmZlclJlY2VpdmVyLnBvc3RDaHVua0F1ZGlvQnVmZmVyKGFkLHRoaXMuY2h1bmtJZHgpO1xyXG4gICAgICAgIHRoaXMuY2h1bmtJZHgrKztcclxuICAgICAgfWNhdGNoKGVycil7XHJcbiAgICAgICAgLy8gVE9ETyBIYW5kbGUgZXJyb3JzXHJcbiAgICAgICAgLy8gaU9TIFNhZmFyaSBzb21ldGltZXMgdGhyb3dzIE5vdFN1cHBvcnRlZEVycm9yXHJcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkNvdWxkIG5vdCBjcmVhdGUgYXVkaW8gYnVmZmVyIGZvciBjaHVua2VkIHVwbG9hZC5cIik7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihcIk5yLiBvZiBjaHM6IFwiK3RoaXMuY2hhbm5lbHMrXCIsIGZyYW1lIGxlbmd0aDogXCIrZnJhbWVMZW4rXCIsIHNhbXBsZSByYXRlOiBcIit0aGlzLnNhbXBsZVJhdGUpO1xyXG4gICAgICAgIGlmKGVyciBpbnN0YW5jZW9mIERPTUV4Y2VwdGlvbil7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRE9NIGV4Y2VwdGlvbjogTmFtZTogXCIrZXJyLm5hbWUrXCIsIE1zZzogXCIrZXJyLm1lc3NhZ2UpO1xyXG4gICAgICAgICAgaWYoZXJyLm5hbWU9PT0nTm90U3VwcG9ydGVkRXJyb3InKXtcclxuICAgICAgICAgICAgaWYoZnJhbWVMZW49PTApe1xyXG4gICAgICAgICAgICAgIC8vIEVtcHR5IGJ1ZmZlcnMgYXJlIG5vdCBzdXBwb3J0ZWQgYnkgQ2hyb21pdW1cclxuICAgICAgICAgICAgIC8vIE5vIGRhdGEgdG8gdHJhbnNmZXIsIGJ1dCB0aGlzIGNhc2Ugc2hvdWxkIG5ldmVyIGhhcHBlblxyXG4gICAgICAgICAgICAgIHJldHVybiBmcmFtZUxlbjtcclxuICAgICAgICAgICAgfWVsc2V7XHJcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9ZWxzZSBpZihlcnIubmFtZT09PSdSYW5nZUVycm9yJyl7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJET00gUmFuZ2VFcnJvclwiKTtcclxuICAgICAgICAgICAgLy8gT3V0IG9mIG1lbW9yeVxyXG4gICAgICAgICAgICAvLyBUT0RPIFdoYXQgdG8gZG8gPz9cclxuICAgICAgICAgICAgdGhyb3cgZXJyO1xyXG4gICAgICAgICAgfWVsc2V7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJET00gRXhjZXB0aW9uIHVua25vd25cIik7XHJcbiAgICAgICAgICAgIHRocm93IGVycjtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9ZWxzZSBpZiAoZXJyIGluc3RhbmNlb2YgUmFuZ2VFcnJvcil7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiUmFuZ2VFcnJvcjogTmFtZTogXCIrZXJyLm5hbWUrXCIsIE1zZzogXCIrZXJyLm1lc3NhZ2UpO1xyXG4gICAgICAgICAgLy8gT3V0IG9mIG1lbW9yeVxyXG4gICAgICAgICAgLy8gVE9ETyBXaGF0IHRvIGRvID8/XHJcbiAgICAgICAgICB0aHJvdyBlcnI7XHJcbiAgICAgICAgfWVsc2V7XHJcbiAgICAgICAgICB0aHJvdyBlcnI7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZnJhbWVMZW47XHJcbiAgfVxyXG5cclxufVxyXG5cclxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2ljUmVjb3JkZXIgZXh0ZW5kcyBSZXNwb25zaXZlQ29tcG9uZW50e1xyXG4gIGdldCBhbGxvd0VjaG9DYW5jZWxsYXRpb24oKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5fYWxsb3dFY2hvQ2FuY2VsbGF0aW9uO1xyXG4gIH1cclxuXHJcbiAgc2V0IGFsbG93RWNob0NhbmNlbGxhdGlvbih2YWx1ZTogYm9vbGVhbikge1xyXG4gICAgdGhpcy5fYWxsb3dFY2hvQ2FuY2VsbGF0aW9uID0gdmFsdWU7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgdXBkYXRlVGltZXJJZDogYW55O1xyXG5cclxuICBwcm90ZWN0ZWQgbWF4UmVjVGltZXJJZDogbnVtYmVyfG51bGw9bnVsbDtcclxuICBwcm90ZWN0ZWQgbWF4UmVjVGltZXJSdW5uaW5nOiBib29sZWFuPWZhbHNlO1xyXG5cclxuICBnZXQgbWF4QXV0b05ldE1lbVN0b3JlU2FtcGxlcygpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX21heEF1dG9OZXRNZW1TdG9yZVNhbXBsZXM7XHJcbiAgfVxyXG5cclxuICBzZXQgbWF4QXV0b05ldE1lbVN0b3JlU2FtcGxlcyh2YWx1ZTogbnVtYmVyKSB7XHJcbiAgICB0aGlzLl9tYXhBdXRvTmV0TWVtU3RvcmVTYW1wbGVzID0gdmFsdWU7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfTUFYX05FVF9BVVRPX01FTV9TVE9SRV9TQU1QTEVTOm51bWJlcj0yODgwMDAwKjU7IC8vIERlZmF1bHQgNSBtaW51dGVzIG9uZSBjaGFubmVsIGF0IDQ4a0h6XHJcbiAgcHJvdGVjdGVkIF9tYXhBdXRvTmV0TWVtU3RvcmVTYW1wbGVzOm51bWJlcj1CYXNpY1JlY29yZGVyLkRFRkFVTFRfTUFYX05FVF9BVVRPX01FTV9TVE9SRV9TQU1QTEVTO1xyXG5cclxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfQ0hVTktfU0laRV9TRUNPTkRTOm51bWJlcj0zMDtcclxuXHJcbiAgZ2V0IGNsaWVudEF1ZGlvU3RvcmFnZVR5cGUoKTogQXVkaW9TdG9yYWdlVHlwZSB7XHJcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50QXVkaW9TdG9yYWdlVHlwZTtcclxuICB9XHJcblxyXG4gIHNldCBjbGllbnRBdWRpb1N0b3JhZ2VUeXBlKHZhbHVlOiBBdWRpb1N0b3JhZ2VUeXBlKSB7XHJcblxyXG4gICAgbGV0IG9sZFZhbHVlPXRoaXMuX2NsaWVudEF1ZGlvU3RvcmFnZVR5cGU7XHJcbiAgICB0aGlzLl9jbGllbnRBdWRpb1N0b3JhZ2VUeXBlID0gdmFsdWU7XHJcbiAgICBpZih2YWx1ZSE9PW9sZFZhbHVlKXtcclxuICAgICAgdGhpcy5jb25maWd1cmVTdHJlYW1DYXB0dXJlU3RyZWFtKCk7XHJcbiAgICB9XHJcbiAgfVxyXG4gIGdldCBwZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0KCk6IFBlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQgfCBudWxsIHtcclxuICAgIHJldHVybiB0aGlzLl9wZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0O1xyXG4gIH1cclxuXHJcbiAgc2V0IHBlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQodmFsdWU6IFBlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQgfCBudWxsKSB7XHJcbiAgICBsZXQgb2xkVmFsdWU9dGhpcy5fcGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldDtcclxuICAgIHRoaXMuX3BlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQgPSB2YWx1ZTtcclxuICAgIGlmKHZhbHVlIT09b2xkVmFsdWUpe1xyXG4gICAgICB0aGlzLmNvbmZpZ3VyZVN0cmVhbUNhcHR1cmVTdHJlYW0oKTtcclxuICAgIH1cclxuXHJcbiAgfVxyXG5cclxuICAvLyBFbmFibGUgb25seSBmb3IgZGV2ZWxvcGVtbnQvZGVidWcgcHVycG9zZXMgb2YgYXJyYXkgYXVkaW8gYnVmZmVycyAhIVxyXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgRk9SQ0VfQVJSUkFZX0FVRElPX0JVRkZFUj1mYWxzZTtcclxuXHJcbiAgZ2V0IHVwbG9hZENodW5rU2l6ZVNlY29uZHMoKTogbnVtYmVyfG51bGwge1xyXG4gICAgcmV0dXJuIHRoaXMuX3VwbG9hZENodW5rU2l6ZVNlY29uZHM7XHJcbiAgfVxyXG5cclxuICBzZXQgdXBsb2FkQ2h1bmtTaXplU2Vjb25kcyh2YWx1ZTogbnVtYmVyfG51bGwpIHtcclxuICAgIGxldCBvbGRWYWx1ZT10aGlzLnVwbG9hZENodW5rU2l6ZVNlY29uZHM7XHJcbiAgICB0aGlzLl91cGxvYWRDaHVua1NpemVTZWNvbmRzID0gdmFsdWU7XHJcbiAgICBpZih2YWx1ZSE9PW9sZFZhbHVlKXtcclxuICAgICAgdGhpcy5jb25maWd1cmVTdHJlYW1DYXB0dXJlU3RyZWFtKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgdXNlckFnZW50OlVzZXJBZ2VudDtcclxuICBzdGF0dXNNc2c6IHN0cmluZz0nJztcclxuICBzdGF0dXNBbGVydFR5cGUhOiBzdHJpbmc7XHJcbiAgc3RhdHVzV2FpdGluZzogYm9vbGVhbj1mYWxzZTtcclxuICByZWFkb25seT1mYWxzZTtcclxuICBwcm90ZWN0ZWQgcmZVdWlkOnN0cmluZ3xudWxsPW51bGw7XHJcbiAgcHJvY2Vzc2luZ1JlY29yZGluZz1mYWxzZTtcclxuICBhYzogQXVkaW9DYXB0dXJlfG51bGw9bnVsbDtcclxuXHJcbiAgcHJvdGVjdGVkIF93YWtlTG9jazpib29sZWFuPWZhbHNlO1xyXG4gIC8vIFByb3BlcnR5IGF1ZGlvRGV2aWNlcyBmcm9tIHByb2plY3QgY29uZmlnOiBsaXN0IG9mIG5hbWVzIG9mIGFsbG93ZWQgYXVkaW8gZGV2aWNlcy5cclxuICBwcm90ZWN0ZWQgX2F1ZGlvRGV2aWNlczogQXJyYXk8QXVkaW9EZXZpY2U+IHwgbnVsbHwgdW5kZWZpbmVkO1xyXG4gIHByb3RlY3RlZCBfc2VsZWN0ZWREZXZpY2VJZDpzdHJpbmd8dW5kZWZpbmVkPXVuZGVmaW5lZDtcclxuICBwcm90ZWN0ZWQgc2VsQ2FwdHVyZURldmljZUlkOiBDb25zdHJhaW5ET01TdHJpbmcgfCBudWxsO1xyXG4gIHByb3RlY3RlZCBfY2hhbm5lbENvdW50ID0gMjtcclxuICBwcm90ZWN0ZWQgX2F1dG9HYWluQ29udHJvbENvbmZpZ3M6IEFycmF5PEF1dG9HYWluQ29udHJvbENvbmZpZz4gfCBudWxsfCB1bmRlZmluZWQ7XHJcbiAgcHJvdGVjdGVkIF9hbGxvd0VjaG9DYW5jZWxsYXRpb246Ym9vbGVhbj1mYWxzZTtcclxuXHJcbiAgX3Nlc3Npb246IFNlc3Npb258bnVsbD1udWxsO1xyXG4gIHByb3RlY3RlZCBfcmVjb3JkaW5nRmlsZTpSZWNvcmRpbmdGaWxlfG51bGw9bnVsbDtcclxuXHJcbiAgdHJhbnNwb3J0QWN0aW9uczogVHJhbnNwb3J0QWN0aW9ucztcclxuICBwbGF5U3RhcnRBY3Rpb246IEFjdGlvbjx2b2lkPjtcclxuXHJcbiAgcHJvdGVjdGVkIHN0YXJ0ZWREYXRlOkRhdGV8bnVsbD1udWxsO1xyXG5cclxuICB1cGxvYWRQcm9ncmVzczogbnVtYmVyID0gMTAwO1xyXG4gIHVwbG9hZFN0YXR1czogc3RyaW5nID0gJ29rJ1xyXG4gIHByb3RlY3RlZCB1cGxvYWRTZXQ6VXBsb2FkU2V0fG51bGw9bnVsbDtcclxuXHJcbiAgYXVkaW9TaWduYWxDb2xsYXBzZWQgPSB0cnVlO1xyXG5cclxuICBwcm90ZWN0ZWQgc3RyZWFtTGV2ZWxNZWFzdXJlOiBTdHJlYW1MZXZlbE1lYXN1cmU7XHJcbiAgcHJvdGVjdGVkIGxldmVsTWVhc3VyZTogTGV2ZWxNZWFzdXJlO1xyXG4gIHBlYWtMZXZlbEluRGI6bnVtYmVyPU1JTl9EQl9MRVZFTDtcclxuICBhdWRpb0xvYWRlZDpib29sZWFuPWZhbHNlO1xyXG4gIGRpc2FibGVBdWRpb0RldGFpbHM6Ym9vbGVhbj1mYWxzZTtcclxuICBwcm90ZWN0ZWQgX2NvbnRyb2xBdWRpb1BsYXllcjogQXVkaW9QbGF5ZXJ8bnVsbD1udWxsO1xyXG4gIHB1YmxpYyBkaXNwbGF5QXVkaW9DbGlwOiBBdWRpb0NsaXAgfCBudWxsPW51bGw7XHJcbiAgcHJvdGVjdGVkIGF1ZGlvRmV0Y2hTdWJzY3JpcHRpb246U3Vic2NyaXB0aW9ufG51bGw9bnVsbDtcclxuXHJcbiAgbGl2ZUxldmVsRGlzcGxheVN0YXRlOkxpdmVMZXZlbFN0YXRlPUxpdmVMZXZlbFN0YXRlLlJFQURZO1xyXG4gIGtlZXBMaXZlTGV2ZWw6Ym9vbGVhbj1mYWxzZTtcclxuICBwcml2YXRlIGNhbGNCdWZmZXJJbmZvc1N1YnNjcjpTdWJzY3JpcHRpb258bnVsbD1udWxsO1xyXG5cclxuICBwcm90ZWN0ZWQgZGVzdHJveWVkPWZhbHNlO1xyXG5cclxuICBwcm90ZWN0ZWQgbmF2aWdhdGlvbkRpc2FibGVkPXRydWU7XHJcblxyXG4gIHByb3RlY3RlZCBfdXBsb2FkQ2h1bmtTaXplU2Vjb25kczpudW1iZXJ8bnVsbD1udWxsO1xyXG4gIC8vPUJhc2ljUmVjb3JkZXIuREVGQVVMVF9DSFVOS19TSVpFX1NFQ09ORFM7XHJcblxyXG4gIC8vIERlZmF1bHQ6IENvbnRpbnVvdXMgSFRNTDUgQXVkaW8gQVBJIEF1ZGlvQnVmZmVyLCBubyBjaHVua2VkIHVwbG9hZFxyXG4gIHByb3RlY3RlZCBfY2xpZW50QXVkaW9TdG9yYWdlVHlwZTpBdWRpb1N0b3JhZ2VUeXBlPUF1ZGlvU3RvcmFnZVR5cGUuTUVNX0VOVElSRTtcclxuXHJcbiAgcHJvdGVjdGVkIF9wZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0OlBlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXR8bnVsbD1udWxsO1xyXG5cclxuICBwcm90ZWN0ZWQgX3NjcmVlbkxvY2tlZD1mYWxzZTtcclxuXHJcbiAgcHJpdmF0ZSB3YWtlTG9ja01hbmFnZXI/Oldha2VMb2NrTWFuYWdlcjtcclxuXHJcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBicG86QnJlYWtwb2ludE9ic2VydmVyLHByb3RlY3RlZCBjaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgICAgICAgICAgICAgICBwdWJsaWMgZGlhbG9nOiBNYXREaWFsb2csXHJcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgc2Vzc2lvblNlcnZpY2U6U2Vzc2lvblNlcnZpY2UsXHJcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgdXBsb2FkZXI6IFNwZWVjaFJlY29yZGVyVXBsb2FkZXIsXHJcbiAgICAgICAgICAgICAgICBASW5qZWN0KFNQRUVDSFJFQ09SREVSX0NPTkZJRykgcHVibGljIGNvbmZpZz86IFNwZWVjaFJlY29yZGVyQ29uZmlnKSB7XHJcbiAgICBzdXBlcihicG8pO1xyXG4gICAgdGhpcy51c2VyQWdlbnQ9VXNlckFnZW50QnVpbGRlci51c2VyQWdlbnQoKTtcclxuICAgIGNvbnN0IGRldFBmbT10aGlzLnVzZXJBZ2VudC5kZXRlY3RlZFBsYXRmb3JtO1xyXG4gICAgaWYoZGV0UGZtKSB7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoXCJEZXRlY3RlZCBwbGF0Zm9ybTogXCIgK2RldFBmbSk7XHJcbiAgICB9XHJcbiAgICBjb25zdCBkZXRCcj10aGlzLnVzZXJBZ2VudC5kZXRlY3RlZEJyb3dzZXI7XHJcbiAgICBjb25zdCBkZXRCclZlcnM9dGhpcy51c2VyQWdlbnQuZGV0ZWN0ZWRCcm93c2VyVmVyc2lvbjtcclxuICAgIGlmKGRldEJyKSB7XHJcbiAgICAgIGxldCBkZXRCclZlcnNTdHI9KGRldEJyVmVycyk/JyAnK2RldEJyVmVyczonJztcclxuICAgICAgY29uc29sZS5kZWJ1ZyhcIkRldGVjdGVkIGJyb3dzZXI6IFwiICtkZXRCcitkZXRCclZlcnNTdHIpO1xyXG4gICAgfVxyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zID0gbmV3IFRyYW5zcG9ydEFjdGlvbnMoKTtcclxuICAgIHRoaXMucGxheVN0YXJ0QWN0aW9uID0gbmV3IEFjdGlvbignUGxheScpO1xyXG4gICAgdGhpcy5sZXZlbE1lYXN1cmUgPSBuZXcgTGV2ZWxNZWFzdXJlKCk7XHJcbiAgICB0aGlzLnN0cmVhbUxldmVsTWVhc3VyZSA9IG5ldyBTdHJlYW1MZXZlbE1lYXN1cmUoKTtcclxuICAgIHRoaXMuc2VsQ2FwdHVyZURldmljZUlkID0gbnVsbDtcclxuICB9XHJcblxyXG4gIGdldCB3YWtlTG9jaygpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLl93YWtlTG9jaztcclxuICB9XHJcblxyXG4gIHNldCB3YWtlTG9jayh2YWx1ZTogYm9vbGVhbikge1xyXG4gICAgdGhpcy5fd2FrZUxvY2sgPSB2YWx1ZTtcclxuICB9XHJcblxyXG4gIGVuYWJsZVdha2VMb2NrQ29uZCgpe1xyXG4gICAgaWYodGhpcy53YWtlTG9jaz09PXRydWUpIHtcclxuICAgICAgaWYoIXRoaXMud2FrZUxvY2tNYW5hZ2VyKXtcclxuICAgICAgICB0aGlzLndha2VMb2NrTWFuYWdlcj1uZXcgV2FrZUxvY2tNYW5hZ2VyKCk7XHJcbiAgICAgICAgdGhpcy53YWtlTG9ja01hbmFnZXIuYmVoYXZpb3JTdWJqZWN0LnN1YnNjcmliZSh7XHJcbiAgICAgICAgICAgIG5leHQ6ICh2KSA9PiB7XHJcbiAgICAgICAgICAgICAgdGhpcy5fc2NyZWVuTG9ja2VkID0gdjtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgZXJyb3I6IChlcnIpID0+IHtcclxuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiV2FrZSBsb2NrIGVycm9yIVwiKVxyXG4gICAgICAgICAgICAgIHRoaXMuX3NjcmVlbkxvY2tlZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLndha2VMb2NrTWFuYWdlci5lbmFibGVXYWtlTG9jaygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZGlzYWJsZVdha2VMb2NrQ29uZCgpe1xyXG4gICAgdGhpcy53YWtlTG9ja01hbmFnZXI/LmRpc2FibGVXYWtlTG9jaygpO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHNjcmVlbkxvY2tlZCgpe1xyXG4gICAgcmV0dXJuIHRoaXMuX3NjcmVlbkxvY2tlZDtcclxuICB9XHJcblxyXG4gIHNldCBhdWRpb0RldmljZXMoYXVkaW9EZXZpY2VzOiBBcnJheTxBdWRpb0RldmljZT4gfCBudWxsIHwgdW5kZWZpbmVkKSB7XHJcbiAgICB0aGlzLl9hdWRpb0RldmljZXMgPSBhdWRpb0RldmljZXM7XHJcbiAgfVxyXG5cclxuICBzZXQgYXV0b0dhaW5Db250cm9sQ29uZmlncyhhdXRvR2FpbkNvbnRyb2xDb25maWdzOiBBcnJheTxBdXRvR2FpbkNvbnRyb2xDb25maWc+fG51bGx8dW5kZWZpbmVkKXtcclxuICAgIHRoaXMuX2F1dG9HYWluQ29udHJvbENvbmZpZ3M9YXV0b0dhaW5Db250cm9sQ29uZmlncztcclxuICB9XHJcblxyXG4gIHNldCBjaGFubmVsQ291bnQoY2hhbm5lbENvdW50OiBudW1iZXIpIHtcclxuICAgIHRoaXMuX2NoYW5uZWxDb3VudCA9IGNoYW5uZWxDb3VudDtcclxuICB9XHJcblxyXG4gIHNldCBzZXNzaW9uKHNlc3Npb246IFNlc3Npb258bnVsbCkge1xyXG4gICAgdGhpcy5fc2Vzc2lvbiA9IHNlc3Npb247XHJcbiAgfVxyXG5cclxuICBnZXQgc2Vzc2lvbigpOlNlc3Npb258bnVsbHtcclxuICAgIHJldHVybiB0aGlzLl9zZXNzaW9uO1xyXG4gIH1cclxuXHJcbiAgZW5hYmxlU3RhcnRVc2VyR2VzdHVyZSgpIHtcclxuICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2luZm8nO1xyXG4gICAgdGhpcy5zdGF0dXNNc2cgPSAnUmVhZHkuJztcclxuICB9XHJcblxyXG4gIGNvbmZpZ3VyZVN0cmVhbUNhcHR1cmVTdHJlYW0oKSB7XHJcbiAgICBsZXQgb3V0U3RyZWFtO1xyXG5cclxuICAgIGlmIChBdWRpb1N0b3JhZ2VUeXBlLk1FTV9FTlRJUkUhPT10aGlzLl9jbGllbnRBdWRpb1N0b3JhZ2VUeXBlIHx8IHRoaXMudXBsb2FkQ2h1bmtTaXplU2Vjb25kcykge1xyXG4gICAgICBpZighdGhpcy51cGxvYWRDaHVua1NpemVTZWNvbmRzKXtcclxuICAgICAgICB0aGlzLnVwbG9hZENodW5rU2l6ZVNlY29uZHM9QmFzaWNSZWNvcmRlci5ERUZBVUxUX0NIVU5LX1NJWkVfU0VDT05EUztcclxuICAgICAgfVxyXG4gICAgICAvLyBNdWx0aXBseSB0aGUgY2FwdHVyZSBzdHJlYW0gdG8uLi5cclxuICAgICAgbGV0IHNhc20gPSBuZXcgU2VxdWVuY2VBdWRpb0Zsb2F0MzJPdXRTdHJlYW1NdWx0aXBsaWVyKCk7XHJcblxyXG4gICAgICAvLyAuLi51cGxvYWQgYXVkaW8gZGF0YSBpbiBjaHVua3MuLi5cclxuICAgICAgbGV0IGNoTW5nID0gbmV3IENodW5rTWFuYWdlcih0aGlzKTsgIC8vIFRoZSBjaHVuayBtYW5hZ2VyIGNvbm5lY3RzIHRoZSBjaHVua2VkIGF1ZGlvIHN0cmVhbSB0byB0aGlzIGNsYXNzIHRvIHVwbG9hZCB0aGUgY2h1bmtzXHJcbiAgICAgIGxldCBjaE9zVXBsb2FkID0gbmV3IFNlcXVlbmNlQXVkaW9GbG9hdDMyQ2h1bmtlck91dFN0cmVhbShjaE1uZywgdGhpcy51cGxvYWRDaHVua1NpemVTZWNvbmRzKTsgLy8gVGhlIGF1ZGlvIHN0cmVhbSBjaHVua2VyIGl0c2VsZlxyXG4gICAgICBzYXNtLnNlcXVlbmNlQXVkaW9GbG9hdDMyT3V0U3RyZWFtcy5wdXNoKGNoT3NVcGxvYWQpO1xyXG5cclxuICAgICAgLy8gLi4uYW5kIHRvIG1lYXN1cmUgdGhlIGxldmVsXHJcbiAgICAgIGxldCBjaE9zTHZsTWVhcyA9IG5ldyBTZXF1ZW5jZUF1ZGlvRmxvYXQzMkNodW5rZXJPdXRTdHJlYW0odGhpcy5zdHJlYW1MZXZlbE1lYXN1cmUsIExFVkVMX0JBUl9JTlRFUlZBTExfU0VDT05EUylcclxuICAgICAgc2FzbS5zZXF1ZW5jZUF1ZGlvRmxvYXQzMk91dFN0cmVhbXMucHVzaChjaE9zTHZsTWVhcyk7XHJcblxyXG4gICAgICBvdXRTdHJlYW0gPSBzYXNtO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgb3V0U3RyZWFtID0gbmV3IFNlcXVlbmNlQXVkaW9GbG9hdDMyQ2h1bmtlck91dFN0cmVhbSh0aGlzLnN0cmVhbUxldmVsTWVhc3VyZSwgTEVWRUxfQkFSX0lOVEVSVkFMTF9TRUNPTkRTKTtcclxuICAgIH1cclxuICAgIGlmKHRoaXMuYWMpIHtcclxuICAgICAgdGhpcy5hYy5tYXhBdXRvTmV0TWVtU3RvcmVTYW1wbGVzPXRoaXMuX21heEF1dG9OZXRNZW1TdG9yZVNhbXBsZXM7XHJcbiAgICAgIHRoaXMuYWMuYXVkaW9TdG9yYWdlVHlwZT10aGlzLl9jbGllbnRBdWRpb1N0b3JhZ2VUeXBlO1xyXG4gICAgICB0aGlzLmFjLmF1ZGlvT3V0U3RyZWFtID0gb3V0U3RyZWFtO1xyXG4gICAgICBpZihBdWRpb1N0b3JhZ2VUeXBlLkRCX0NIVU5LRUQ9PT10aGlzLl9jbGllbnRBdWRpb1N0b3JhZ2VUeXBlICYmIHRoaXMuX3BlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQhPT1udWxsKSB7XHJcbiAgICAgICAgdGhpcy5hYy5wZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0ID0gdGhpcy5fcGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcblxyXG4gIHNob3dSZWNvcmRpbmcoKSB7XHJcbiAgICBpZih0aGlzLl9jb250cm9sQXVkaW9QbGF5ZXIpIHtcclxuICAgICAgdGhpcy5fY29udHJvbEF1ZGlvUGxheWVyLnN0b3AoKTtcclxuICAgIH1cclxuICAgIGlmKHRoaXMuY2FsY0J1ZmZlckluZm9zU3Vic2NyKXtcclxuICAgICAgdGhpcy5jYWxjQnVmZmVySW5mb3NTdWJzY3IudW5zdWJzY3JpYmUoKTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmRpc3BsYXlBdWRpb0NsaXApIHtcclxuICAgICAgbGV0IGRhcD10aGlzLmRpc3BsYXlBdWRpb0NsaXA7XHJcbiAgICAgIGxldCBhZGg9ZGFwLmF1ZGlvRGF0YUhvbGRlcjtcclxuICAgICAgaWYoYWRoKXtcclxuICAgICAgICBpZighdGhpcy5rZWVwTGl2ZUxldmVsKSB7XHJcbiAgICAgICAgICB0aGlzLmxpdmVMZXZlbERpc3BsYXlTdGF0ZSA9IExpdmVMZXZlbFN0YXRlLkxPQURJTkc7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGFkaC5hZGRPblJlYWR5TGlzdGVuZXIoKCk9PntcclxuICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIkF1ZGlvIGRhdGEgaG9sZGVyIHJlYWR5LiBFbmFibGUgcGxheWJhY2suIEF1ZGlvIGxvYWRlZCB0cnVlLlwiKVxyXG4gICAgICAgICAgaWYoIXRoaXMua2VlcExpdmVMZXZlbCkge1xyXG4gICAgICAgICAgICB0aGlzLmxpdmVMZXZlbERpc3BsYXlTdGF0ZSA9IExpdmVMZXZlbFN0YXRlLlJFTkRFUklORztcclxuICAgICAgICAgICAgdGhpcy5jYWxjQnVmZmVySW5mb3NTdWJzY3IgPSB0aGlzLmxldmVsTWVhc3VyZS5jYWxjQnVmZmVyTGV2ZWxJbmZvcyhhZGgsIExFVkVMX0JBUl9JTlRFUlZBTExfU0VDT05EUykuc3Vic2NyaWJlKChsZXZlbEluZm9zKSA9PiB7XHJcbiAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwiTGV2ZWwgaW5mb3M6IGxldmVsSW5mb3MgbnVtYmVyIHNpemU6IFwiK2xldmVsSW5mb3MubnVtYmVyU2l6ZSgpKTtcclxuICAgICAgICAgICAgICBkYXAubGV2ZWxJbmZvcyA9IGxldmVsSW5mb3M7XHJcbiAgICAgICAgICAgICAgdGhpcy5saXZlTGV2ZWxEaXNwbGF5U3RhdGUgPSBMaXZlTGV2ZWxTdGF0ZS5SRUFEWTtcclxuICAgICAgICAgICAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICB0aGlzLnBsYXlTdGFydEFjdGlvbi5kaXNhYmxlZCA9IGZhbHNlO1xyXG4gICAgICAgICAgdGhpcy5hdWRpb0xvYWRlZD10cnVlO1xyXG4gICAgICAgICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwiQXVkaW8gZGF0YSBob2xkZXIgYWRkZWQgb25SZWFkeS5cIilcclxuICAgICAgfVxyXG4gICAgICAvL3RoaXMucGxheVN0YXJ0QWN0aW9uLmRpc2FibGVkID0gZmFsc2U7XHJcbiAgICB9IGVsc2Uge1xyXG5cclxuICAgICAgdGhpcy5wbGF5U3RhcnRBY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgICB0aGlzLmF1ZGlvTG9hZGVkPWZhbHNlO1xyXG4gICAgICAvLyBDb2xsYXBzZSBhdWRpbyBzaWduYWwgZGlzcGxheSBpZiBvcGVuXHJcbiAgICAgIGlmICghdGhpcy5hdWRpb1NpZ25hbENvbGxhcHNlZCkge1xyXG4gICAgICAgIHRoaXMuYXVkaW9TaWduYWxDb2xsYXBzZWQgPSB0cnVlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcclxuICB9XHJcblxyXG4gIHN0YXJ0KCkge1xyXG4gICAgdGhpcy5zdGF0dXNBbGVydFR5cGUgPSAnaW5mbyc7XHJcbiAgICB0aGlzLnN0YXR1c01zZyA9ICdTdGFydGluZyBzZXNzaW9uLi4uJztcclxuICAgIHRoaXMuc3RhdHVzV2FpdGluZz1mYWxzZTtcclxuICAgIGlmKHRoaXMuX3Nlc3Npb24pIHtcclxuICAgICAgaWYgKHRoaXMuX3Nlc3Npb24uc2VhbGVkKSB7XHJcbiAgICAgICAgdGhpcy5yZWFkb25seSA9IHRydWVcclxuICAgICAgICB0aGlzLnN0YXR1c01zZyA9ICdTZXNzaW9uIHNlYWxlZCEnO1xyXG4gICAgICAgIC8vbGV0IGRpYWxvZ1JlZiA9IHRoaXMuZGlhbG9nLm9wZW4oU2Vzc2lvblNlYWxlZERpYWxvZywge30pO1xyXG4gICAgICAgIHRoaXMuZGlhbG9nLm9wZW4oTWVzc2FnZURpYWxvZywge1xyXG4gICAgICAgICAgZGF0YToge1xyXG4gICAgICAgICAgICB0eXBlOiAnZXJyb3InLFxyXG4gICAgICAgICAgICB0aXRsZTogJ0Vycm9yJyxcclxuICAgICAgICAgICAgbXNnOiBcIlRoaXMgc2Vzc2lvbiBpcyBzZWFsZWQuIFJlY29yZGluZ3MgY2Fubm90IGJlIGFkZGVkIGFueW1vcmUuXCIsXHJcbiAgICAgICAgICAgIGFkdmljZTogJ1BsZWFzZSBhc2sgeW91ciBleHBlcmltZW50ZXIgd2hhdCB0byBkbyAoZS5nIHN0YXJ0IGEgbmV3IHNlc3Npb24pLicsXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgbGV0IGJvZHk6IGFueSA9IHt9O1xyXG4gICAgICAgIGlmICh0aGlzLl9zZXNzaW9uLnN0YXR1cyA9PT0gXCJDUkVBVEVEXCIpIHtcclxuICAgICAgICAgIHRoaXMuX3Nlc3Npb24uc3RhdHVzID0gXCJMT0FERURcIjtcclxuICAgICAgICAgIGJvZHkuc3RhdHVzID0gdGhpcy5fc2Vzc2lvbi5zdGF0dXM7XHJcbiAgICAgICAgICBpZiAoIXRoaXMuX3Nlc3Npb24ubG9hZGVkRGF0ZSkge1xyXG4gICAgICAgICAgICB0aGlzLl9zZXNzaW9uLmxvYWRlZERhdGUgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgICAgICBib2R5LmxvYWRlZERhdGUgPSB0aGlzLl9zZXNzaW9uLmxvYWRlZERhdGU7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMuX3Nlc3Npb24ucmVzdGFydGVkRGF0ZSA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgICBib2R5LnJlc3RhcnRlZERhdGUgPSB0aGlzLl9zZXNzaW9uLnJlc3RhcnRlZERhdGU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuc2Vzc2lvblNlcnZpY2UucGF0Y2hTZXNzaW9uT2JzZXJ2ZXIodGhpcy5fc2Vzc2lvbiwgYm9keSkuc3Vic2NyaWJlKClcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIENoZWNrIGJyb3dzZXIgY29tcGF0aWJpbGl0eVxyXG4gICAgaWYodGhpcy51c2VyQWdlbnQuZGV0ZWN0ZWRCcm93c2VyPT09QnJvd3Nlci5TYWZhcmkgJiYgdGhpcy5fY2hhbm5lbENvdW50PjEpe1xyXG4gICAgICBsZXQgZU1zZz1cIkVycm9yOiBTYWZhcmkgYnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IHN0ZXJlbyByZWNvcmRpbmdzLlwiO1xyXG4gICAgICBjb25zb2xlLmVycm9yKGVNc2cpO1xyXG4gICAgICB0aGlzLmRpYWxvZy5vcGVuKE1lc3NhZ2VEaWFsb2csIHtcclxuICAgICAgICBkYXRhOiB7XHJcbiAgICAgICAgICB0eXBlOiAnZXJyb3InLFxyXG4gICAgICAgICAgdGl0bGU6ICdCcm93c2VyIG5vdCBzdXBwb3J0ZWQnLFxyXG4gICAgICAgICAgbXNnOiBlTXNnLFxyXG4gICAgICAgICAgYWR2aWNlOiBcIlBsZWFzZSB1c2UgYSBzdXBwb3J0ZWQgYnJvd3NlciwgZS5nLiBNb3ppbGxhIEZpcmVmb3guXCJcclxuICAgICAgICB9XHJcbiAgICAgIH0pXHJcbiAgICB9XHJcblxyXG4gICAgLy9jb25zb2xlLmxvZyhcIlNlc3Npb24gSUQ6IFwiK3RoaXMuX3Nlc3Npb24uc2Vzc2lvbisgXCIgc3RhdHVzOiBcIit0aGlzLl9zZXNzaW9uLnN0YXR1cylcclxuICAgIHRoaXMuX3NlbGVjdGVkRGV2aWNlSWQ9dW5kZWZpbmVkO1xyXG5cclxuICAgIGlmICghdGhpcy5yZWFkb25seSAmJiB0aGlzLmFjICYmIChGT1JDRV9SRVFVRVNUX0FVRElPX1BFUk1JU1NJT05TIHx8ICh0aGlzLl9hdWRpb0RldmljZXMgJiYgdGhpcy5fYXVkaW9EZXZpY2VzLmxlbmd0aCA+IDApKSkge1xyXG4gICAgICB0aGlzLnN0YXR1c01zZyA9ICdSZXF1ZXN0aW5nIGF1ZGlvIHBlcm1pc3Npb25zLi4uJztcclxuICAgICAgdGhpcy5zdGF0dXNBbGVydFR5cGUgPSAnaW5mbyc7XHJcblxyXG4gICAgICB0aGlzLmFjLmRldmljZUluZm9zKChtZGlzKSA9PiB7XHJcbiAgICAgICAgbGV0IGF1ZGlvQ2FwdHVyZURldmljZUF2YWlsOiBib29sZWFuID0gZmFsc2U7XHJcbiAgICAgICAgbGV0IGF1ZGlvUGxheURldmljZUF2YWlsOiBib29sZWFuID0gZmFsc2U7XHJcbiAgICAgICAgaWYgKG1kaXMpIHtcclxuICAgICAgICAgIGlmKHRoaXMuYWMpIHtcclxuICAgICAgICAgICAgdGhpcy5hYy5wcmludERldmljZXMobWRpcyk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZiAobWRpcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIGZvciAobGV0IG1kaWkgPSAwOyBtZGlpIDwgbWRpcy5sZW5ndGg7IG1kaWkrKykge1xyXG4gICAgICAgICAgICAgIGxldCBtZGkgPSBtZGlzW21kaWldO1xyXG4gICAgICAgICAgICAgIGxldCBraW5kPW1kaS5raW5kO1xyXG4gICAgICAgICAgICAgIGlmKGtpbmQgPT09IFwiYXVkaW9pbnB1dFwiKXtcclxuICAgICAgICAgICAgICAgIGF1ZGlvQ2FwdHVyZURldmljZUF2YWlsPXRydWU7XHJcbiAgICAgICAgICAgICAgfWVsc2UgaWYoa2luZD09PSBcImF1ZGlvb3V0cHV0XCIpe1xyXG4gICAgICAgICAgICAgICAgYXVkaW9QbGF5RGV2aWNlQXZhaWw9dHJ1ZTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAodGhpcy5fc2Vzc2lvbiAmJiB0aGlzLl9zZXNzaW9uLnR5cGUgIT09ICdURVNUX0RFRl9BJyAmJiB0aGlzLl9hdWRpb0RldmljZXMgJiYgdGhpcy5fYXVkaW9EZXZpY2VzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgbGV0IGZkaTogTWVkaWFEZXZpY2VJbmZvIHwgbnVsbCA9IG51bGw7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGFkSSA9IDA7IGFkSSA8IHRoaXMuX2F1ZGlvRGV2aWNlcy5sZW5ndGg7IGFkSSsrKSB7XHJcbiAgICAgICAgICAgICAgbGV0IGFkID0gdGhpcy5fYXVkaW9EZXZpY2VzW2FkSV07XHJcbiAgICAgICAgICAgICAgaWYgKGFkLnBsYXliYWNrKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBwcm9qZWN0IGF1ZGlvIGRldmljZSBjb25maWcgZm9yIHBsYXliYWNrIGRldmljZVxyXG4gICAgICAgICAgICAgICAgLy8gbm90IHVzZWQgZm9yIG5vd1xyXG4gICAgICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIGZvciAobGV0IG1kaWkgPSAwOyBtZGlpIDwgbWRpcy5sZW5ndGg7IG1kaWkrKykge1xyXG4gICAgICAgICAgICAgICAgbGV0IG1kaSA9IG1kaXNbbWRpaV07XHJcbiAgICAgICAgICAgICAgICBsZXQga2luZD1tZGkua2luZDtcclxuICAgICAgICAgICAgICAgIGlmKGtpbmQgPT09IFwiYXVkaW9pbnB1dFwiKXtcclxuICAgICAgICAgICAgICAgICAgYXVkaW9DYXB0dXJlRGV2aWNlQXZhaWw9dHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1lbHNlIGlmKGtpbmQ9PT0gXCJhdWRpb291dHB1dFwiKXtcclxuICAgICAgICAgICAgICAgICAgYXVkaW9QbGF5RGV2aWNlQXZhaWw9dHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChhZC5yZWdleCkge1xyXG4gICAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiTWF0Y2g/OiBcXCdcIittZGkubGFiZWwrXCJcXCcgXFwnXCIrYWQubmFtZStcIlxcJ1wiKTtcclxuICAgICAgICAgICAgICAgICAgaWYgKG1kaS5sYWJlbC5tYXRjaChhZC5uYW1lKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGZkaSA9IG1kaTtcclxuICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiTWF0Y2ghXCIpO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICBpZiAobWRpLmxhYmVsLnRyaW0oKSA9PT0gYWQubmFtZS50cmltKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBmZGkgPSBtZGk7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChmZGkpIHtcclxuICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIGlmIChmZGkpIHtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGZkaSkge1xyXG4gICAgICAgICAgICAgIC8vIG1hdGNoaW5nIGRldmljZSBmb3VuZFxyXG5cclxuICAgICAgICAgICAgICAvLyBOb3QgYWJsZSB0byBvcGVuIGRldmljZSBoZXJlIHNpbmNlIENocm9tZSA3MVxyXG4gICAgICAgICAgICAgIC8vIENocm9tZSA3MSByZXF1aXJlcyBhIHVzZXIgZ2VzdHVyZSBiZWZvcmUgdGhlIEF1ZGlvQ29udGV4dCBjYW4gYmUgcmVzdW1lZFxyXG4gICAgICAgICAgICAgIC8vIHNlc3Npb25tYW5hZ2VyLnRzOjcxMiBPcGVuIHNlc3Npb24gd2l0aCBkZWZhdWx0IGF1ZGlvIGRldmljZSBmb3IgMSBjaGFubmVsc1xyXG4gICAgICAgICAgICAgIC8vIGNhcHR1cmUudHM6MTI4IFRoZSBBdWRpb0NvbnRleHQgd2FzIG5vdCBhbGxvd2VkIHRvIHN0YXJ0LiBJdCBtdXN0IGJlIHJlc3VtZWQgKG9yIGNyZWF0ZWQpIGFmdGVyIGEgdXNlciBnZXN0dXJlIG9uIHRoZSBwYWdlLiBodHRwczovL2dvby5nbC83SzdXTHVcclxuICAgICAgICAgICAgICAvLyBwdXNoLi4vcHJvamVjdHMvc3BlZWNocmVjb3JkZXJuZy9zcmMvbGliL2F1ZGlvL2NhcHR1cmUvY2FwdHVyZS50cy5BdWRpb0NhcHR1cmUub3BlbiBAIGNhcHR1cmUudHM6MTI4XHJcblxyXG4gICAgICAgICAgICAgIC8vdGhpcy5hYy5vcGVuKHRoaXMuX2NoYW5uZWxDb3VudCwgZmRpLmRldmljZUlkKTtcclxuICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJTZXQgc2VsZWN0ZWQgYXVkaW8gZGV2aWNlOiBcXCdcIiArIGZkaS5sYWJlbCArIFwiXFwnIElkOiBcXCdcIiArIGZkaS5kZXZpY2VJZCArIFwiXFwnXCIpO1xyXG4gICAgICAgICAgICAgIHRoaXMuX3NlbGVjdGVkRGV2aWNlSWQgPSBmZGkuZGV2aWNlSWQ7XHJcblxyXG4gICAgICAgICAgICAgIHRoaXMuZW5hYmxlU3RhcnRVc2VyR2VzdHVyZSgpXHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgLy8gZGV2aWNlIG5vdCBmb3VuZFxyXG4gICAgICAgICAgICAgIHRoaXMuc3RhdHVzTXNnID0gJ0VSUk9SOiBSZXF1aXJlZCBhdWRpbyBkZXZpY2Ugbm90IGF2YWlsYWJsZSEnO1xyXG4gICAgICAgICAgICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2Vycm9yJztcclxuICAgICAgICAgICAgICB0aGlzLnJlYWRvbmx5ID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgICAgdGhpcy5kaWFsb2cub3BlbihNZXNzYWdlRGlhbG9nLCB7XHJcbiAgICAgICAgICAgICAgICBkYXRhOiB7XHJcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdlcnJvcicsXHJcbiAgICAgICAgICAgICAgICAgIHRpdGxlOiAnUmVxdWlyZWQgYXVkaW8gZGV2aWNlJyxcclxuICAgICAgICAgICAgICAgICAgbXNnOiBcIlJlcXVpcmVkIGF1ZGlvIGRldmljZSBub3QgZm91bmRcIixcclxuICAgICAgICAgICAgICAgICAgYWR2aWNlOiBcIlBsZWFzZSBjb25uZWN0IGEgc3VpdGFibGUgYXVkaW8gZGV2aWNlIGZvciB0aGlzIHByb2plY3QgYW5kIHJldHJ5IChwcmVzcyB0aGUgYnJvd3NlciByZWxvYWQgYnV0dG9uKS5cIlxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1lbHNle1xyXG4gICAgICAgICAgICBpZighYXVkaW9DYXB0dXJlRGV2aWNlQXZhaWwgJiYgIWF1ZGlvUGxheURldmljZUF2YWlsKXtcclxuICAgICAgICAgICAgICAvLyBubyBkZXZpY2UgZm91bmRcclxuICAgICAgICAgICAgICB0aGlzLnN0YXR1c01zZyA9ICdFUlJPUjogTm8gYXVkaW8gZGV2aWNlIGF2YWlsYWJsZSEnO1xyXG4gICAgICAgICAgICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ3dhcm4nO1xyXG4gICAgICAgICAgICAgIC8vdGhpcy5yZWFkb25seSA9IHRydWU7XHJcblxyXG4gICAgICAgICAgICAgIHRoaXMuZGlhbG9nLm9wZW4oTWVzc2FnZURpYWxvZywge1xyXG4gICAgICAgICAgICAgICAgZGF0YToge1xyXG4gICAgICAgICAgICAgICAgICB0eXBlOiAnd2FybicsXHJcbiAgICAgICAgICAgICAgICAgIHRpdGxlOiAnTm8gYXVkaW8gZGV2aWNlJyxcclxuICAgICAgICAgICAgICAgICAgbXNnOiBcIk5vIGF1ZGlvIGRldmljZSBmb3VuZFwiLFxyXG4gICAgICAgICAgICAgICAgICBhZHZpY2U6IFwiUGxlYXNlIGNvbm5lY3QgYW4gYXVkaW8gZGV2aWNlIGFuZCByZXRyeSAocHJlc3MgdGhlIGJyb3dzZXIgcmVsb2FkIGJ1dHRvbikgb3IgdHJ5IHRvIGNvbnRpbnVlIGFueXdheS5cIlxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIH1lbHNlIHtcclxuICAgICAgICAgICAgICBpZiAoIXRoaXMucmVhZG9ubHkgJiYgIWF1ZGlvQ2FwdHVyZURldmljZUF2YWlsKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBubyBkZXZpY2UgZm91bmRcclxuICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzTXNnID0gJ1dBUk5JTkc6IE5vIGF1ZGlvIGNhcHR1cmUgZGV2aWNlIGF2YWlsYWJsZSEnO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0dXNBbGVydFR5cGUgPSAnd2FybmluZyc7XHJcbiAgICAgICAgICAgICAgICAvL3RoaXMucmVhZG9ubHkgPSB0cnVlO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuZGlhbG9nLm9wZW4oTWVzc2FnZURpYWxvZywge1xyXG4gICAgICAgICAgICAgICAgICBkYXRhOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3dhcm5pbmcnLFxyXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiAnTm8gYXVkaW8gY2FwdHVyZSBkZXZpY2UnLFxyXG4gICAgICAgICAgICAgICAgICAgIG1zZzogXCJObyBhdWRpbyBjYXB0dXJlIGRldmljZSBmb3VuZFwiLFxyXG4gICAgICAgICAgICAgICAgICAgIGFkdmljZTogXCJQbGVhc2UgY29ubmVjdCBhbiBhdWRpbyBjYXB0dXJlIGRldmljZSBhbmQgcmV0cnkgKHByZXNzIHRoZSBicm93c2VyIHJlbG9hZCBidXR0b24pIG9yIHRyeSB0byBjb250aW51ZSBhbnl3YXkuXCJcclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgLy8gU2FmYXJpIGRvZXMgbm90IGxpc3QgcGxheWJhY2sgZGV2aWNlc1xyXG4gICAgICAgICAgICAgIGlmICghYXVkaW9QbGF5RGV2aWNlQXZhaWwpIHtcclxuICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggZG9lcyBub3QgZW51bWVyYXRlIGF1ZGlvb3V0cHV0IGRldmljZXNcclxuICAgICAgICAgICAgICAgIC8vIERvIG5vdCBzaG93IHRoaXMgd2FybmluZywgYmVjYXVzZSBpdCB3b3VsZCBhbHdheXMgYXBwZWFyIG9uIEZpcmVmb3hcclxuICAgICAgICAgICAgICAgIC8vIFdoZW4gaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTQ5ODUxMiBpcyBmaXhlZCB0aGUgd2FybmluZyBjYW4gYmUgZW5hYmxlZCBmb3IgRmlyZWZveCBhcyB3ZWxsXHJcblxyXG4gICAgICAgICAgICAgICAgLy8gSXQgaXMgYWxyZWFkeSBpbXBsZW1uZXRlZCBidXQga2VwdCBiZWhpbmQgYSBwcmVmZXJlbmNlIHNldHRpbmcgaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTE1MjQwMVxyXG5cclxuXHJcbiAgICAgICAgICAgICAgICAvLyBPdXRwdXQgZGV2aWNlcyBhcmUgbGlzdGVkIGlmIGFib3V0OmNvbmZpZyBtZWRpYS5zZXRzaW5raWQuZW5hYmxlZD10cnVlXHJcbiAgICAgICAgICAgICAgICAvLyBidXQgZGVmYXVsdCBzZXR0aW5nIGlzIGZhbHNlXHJcblxyXG5cclxuICAgICAgICAgICAgICAgIC8vIFNhbWUgcHJvYmxlbSB3aXRoIFNhZmFyaVxyXG5cclxuICAgICAgICAgICAgICAgIGlmICghKHRoaXMudXNlckFnZW50LmRldGVjdGVkQnJvd3Nlcj09PUJyb3dzZXIuU2FmYXJpIHx8IHRoaXMudXNlckFnZW50LmRldGVjdGVkQnJvd3Nlcj09PUJyb3dzZXIuRmlyZWZveCkpIHtcclxuICAgICAgICAgICAgICAgICAgLy8gbm8gZGV2aWNlIGZvdW5kXHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzTXNnID0gJ1dBUk5JTkc6IE5vIGF1ZGlvIHBsYXliYWNrIGRldmljZSBhdmFpbGFibGUhJztcclxuICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0dXNBbGVydFR5cGUgPSAnd2Fybic7XHJcbiAgICAgICAgICAgICAgICAgIC8vdGhpcy5yZWFkb25seSA9IHRydWU7XHJcblxyXG4gICAgICAgICAgICAgICAgICB0aGlzLmRpYWxvZy5vcGVuKE1lc3NhZ2VEaWFsb2csIHtcclxuICAgICAgICAgICAgICAgICAgICBkYXRhOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnd2FybicsXHJcbiAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogJ05vIGF1ZGlvIHBsYXliYWNrIGRldmljZScsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtc2c6IFwiTm8gYXVkaW8gcGxheWJhY2sgZGV2aWNlIGZvdW5kXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICBhZHZpY2U6IFwiUGxlYXNlIGNvbm5lY3QgYW4gYXVkaW8gcGxheWJhY2sgZGV2aWNlIGFuZCByZXRyeSAocHJlc3MgdGhlIGJyb3dzZXIgcmVsb2FkIGJ1dHRvbikgb3IgdHJ5IHRvIGNvbnRpbnVlIGFueXdheS5cIlxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIE5vdCBhYmxlIHRvIG9wZW4gZGV2aWNlIGhlcmUgc2luY2UgQ2hyb21lIDcxXHJcbiAgICAgICAgICAgIC8vIENocm9tZSA3MSByZXF1aXJlcyBhIHVzZXIgZ2VzdHVyZSBiZWZvcmUgdGhlIEF1ZGlvQ29udGV4dCBjYW4gYmUgcmVzdW1lZFxyXG4gICAgICAgICAgICAvLyBzZXNzaW9ubWFuYWdlci50czo3MTIgT3BlbiBzZXNzaW9uIHdpdGggZGVmYXVsdCBhdWRpbyBkZXZpY2UgZm9yIDEgY2hhbm5lbHNcclxuICAgICAgICAgICAgLy8gY2FwdHVyZS50czoxMjggVGhlIEF1ZGlvQ29udGV4dCB3YXMgbm90IGFsbG93ZWQgdG8gc3RhcnQuIEl0IG11c3QgYmUgcmVzdW1lZCAob3IgY3JlYXRlZCkgYWZ0ZXIgYSB1c2VyIGdlc3R1cmUgb24gdGhlIHBhZ2UuIGh0dHBzOi8vZ29vLmdsLzdLN1dMdVxyXG4gICAgICAgICAgICAvLyBwdXNoLi4vcHJvamVjdHMvc3BlZWNocmVjb3JkZXJuZy9zcmMvbGliL2F1ZGlvL2NhcHR1cmUvY2FwdHVyZS50cy5BdWRpb0NhcHR1cmUub3BlbiBAIGNhcHR1cmUudHM6MTI4XHJcbiAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJPcGVuIHNlc3Npb24gd2l0aCBkZWZhdWx0IGF1ZGlvIGRldmljZSBmb3IgXCIrdGhpcy5fY2hhbm5lbENvdW50K1wiIGNoYW5uZWxzXCIpO1xyXG4gICAgICAgICAgICAvL3RoaXMuYWMub3Blbih0aGlzLl9jaGFubmVsQ291bnQpO1xyXG5cclxuICAgICAgICAgICAgLy8gZW5hYmxlIHN0YXJ0IGdlc3R1cmUgYW55d2F5XHJcbiAgICAgICAgICAgIHRoaXMuZW5hYmxlU3RhcnRVc2VyR2VzdHVyZSgpXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnN0YXR1c01zZz0nUmVhZHkuJztcclxuICB9XHJcblxyXG4gIHN0YXJ0SXRlbSgpIHtcclxuICAgIHRoaXMucmZVdWlkID0gVVVJRC5nZW5lcmF0ZSgpO1xyXG4gICAgaWYodGhpcy5hYykge1xyXG4gICAgICB0aGlzLmFjLnJlY1VVSUQgPSB0aGlzLnJmVXVpZDtcclxuICAgIH1cclxuICAgIHRoaXMuc3RhcnRlZERhdGU9bnVsbDtcclxuICAgIHRoaXMuZW5hYmxlV2FrZUxvY2tDb25kKCk7XHJcbiAgICAvL3RoaXMucmZVdWlkPVVVSUQuZ2VuZXJhdGUoKTtcclxuICAgIHRoaXMudXBsb2FkU2V0PW51bGw7XHJcbiAgICB0aGlzLnRyYW5zcG9ydEFjdGlvbnMuc3RhcnRBY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgdGhpcy50cmFuc3BvcnRBY3Rpb25zLnBhdXNlQWN0aW9uLmRpc2FibGVkID0gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHByb3RlY3RlZCBzdGFydENhcHR1cmUoKSB7XHJcbiAgICBpZiAodGhpcy5hYykge1xyXG4gICAgICBpZiAoIXRoaXMuYWMub3BlbmVkKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX3NlbGVjdGVkRGV2aWNlSWQpIHtcclxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiT3BlbiBzZXNzaW9uIHdpdGggYXVkaW8gZGV2aWNlIElkOiBcXCdcIiArIHRoaXMuX3NlbGVjdGVkRGV2aWNlSWQgKyBcIlxcJyBmb3IgXCIgKyB0aGlzLl9jaGFubmVsQ291bnQgKyBcIiBjaGFubmVsc1wiKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgY29uc29sZS5sb2coXCJPcGVuIHNlc3Npb24gd2l0aCBkZWZhdWx0IGF1ZGlvIGRldmljZSBmb3IgXCIgKyB0aGlzLl9jaGFubmVsQ291bnQgKyBcIiBjaGFubmVsc1wiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5hYy5vcGVuKHRoaXMuX2NoYW5uZWxDb3VudCwgdGhpcy5fc2VsZWN0ZWREZXZpY2VJZCwgdGhpcy5fYXV0b0dhaW5Db250cm9sQ29uZmlncyx0aGlzLl9hbGxvd0VjaG9DYW5jZWxsYXRpb24pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuYWMuc3RhcnQoKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb3BlbmVkKCkge1xyXG4gICAgaWYodGhpcy5hYykge1xyXG4gICAgICB0aGlzLmFjLnN0YXJ0KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzdGFydGVkKCkge1xyXG5cclxuICAgIGlmKCF0aGlzLnN0YXJ0ZWREYXRlKSB7XHJcbiAgICAgIHRoaXMuc3RhcnRlZERhdGU9bmV3IERhdGUoKTtcclxuICAgIH1cclxuICAgIHRoaXMudHJhbnNwb3J0QWN0aW9ucy5zdGFydEFjdGlvbi5kaXNhYmxlZCA9IHRydWU7XHJcbiAgfVxyXG5cclxuICBwb3N0UmVjb3JkaW5nKHdhdkZpbGU6IFVpbnQ4QXJyYXksIHJlY1VybDogc3RyaW5nLHJmOlJlY29yZGluZ0ZpbGV8bnVsbCx1cGxvYWRIb2xkZXI/OlVwbG9hZEhvbGRlcikge1xyXG4gICAgbGV0IHdhdkJsb2IgPSBuZXcgQmxvYihbd2F2RmlsZV0sIHt0eXBlOiAnYXVkaW8vd2F2J30pO1xyXG4gICAgbGV0IHVsID0gbmV3IFVwbG9hZCh3YXZCbG9iLCByZWNVcmwscmYpO1xyXG4gICAgaWYodXBsb2FkSG9sZGVyKXtcclxuICAgICAgdXBsb2FkSG9sZGVyLnVwbG9hZD11bDtcclxuICAgIH1cclxuICAgIHRoaXMudXBsb2FkZXIucXVldWVVcGxvYWQodWwpO1xyXG4gIH1cclxuXHJcbiAgcG9zdEF1ZGlvU3RyZWFtU3RhcnQoKTogdm9pZCB7XHJcbiAgICBpZih0aGlzLnJmVXVpZCkge1xyXG4gICAgICB0aGlzLnVwbG9hZFNldD1uZXcgVXBsb2FkU2V0KCk7XHJcbiAgICAgIGxldCBhcGlFbmRQb2ludCA9ICcnO1xyXG4gICAgICBpZiAodGhpcy5jb25maWcgJiYgdGhpcy5jb25maWcuYXBpRW5kUG9pbnQpIHtcclxuICAgICAgICBhcGlFbmRQb2ludCA9IHRoaXMuY29uZmlnLmFwaUVuZFBvaW50O1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChhcGlFbmRQb2ludCAhPT0gJycpIHtcclxuICAgICAgICBhcGlFbmRQb2ludCA9IGFwaUVuZFBvaW50ICsgJy8nXHJcbiAgICAgIH1cclxuICAgICAgbGV0IHNlc3Npb25zVXJsID0gYXBpRW5kUG9pbnQgKyBTZXNzaW9uU2VydmljZS5TRVNTSU9OX0FQSV9DVFg7XHJcbiAgICAgIGxldCByZWNVcmw6IHN0cmluZyA9IHNlc3Npb25zVXJsICsgJy8nICsgdGhpcy5zZXNzaW9uPy5zZXNzaW9uSWQgKyAnLycgKyBSRUNGSUxFX0FQSV9DVFggKyAnLycgKyB0aGlzLnJmVXVpZCArICcvcHJlcGFyZUNodW5rc1JlcXVlc3QnO1xyXG4gICAgICBsZXQgZmQgPSBuZXcgRm9ybURhdGEoKTtcclxuICAgICAgLy8gTm90ZTogQXQgbGVhc3Qgb25lIHBhcmFtZXRlciBtdXN0IGJlIHNldFxyXG4gICAgICBmZC5zZXQoJ3V1aWQnLHRoaXMucmZVdWlkKTtcclxuICAgICAgaWYoIXRoaXMuc3RhcnRlZERhdGUpIHtcclxuICAgICAgICB0aGlzLnN0YXJ0ZWREYXRlPW5ldyBEYXRlKCk7XHJcbiAgICAgIH1cclxuICAgICAgZmQuc2V0KCdzdGFydGVkRGF0ZScsdGhpcy5zdGFydGVkRGF0ZS50b0pTT04oKSk7XHJcblxyXG4gICAgICBsZXQgdWwgPSBuZXcgVXBsb2FkKGZkLCByZWNVcmwpO1xyXG4gICAgICB0aGlzLnVwbG9hZFNldC5hZGQodWwpO1xyXG4gICAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlVXBsb2FkKHVsKTtcclxuICAgIH1lbHNle1xyXG4gICAgICBjb25zb2xlLmVycm9yKFwiUmVjb3JkaW5nIGZpbGUgVVVJRCBub3Qgc2V0IVwiKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbnByb3RlY3RlZCBzZXNzaW9uc0Jhc2VVcmwoKTpzdHJpbmcge1xyXG4gIGxldCBhcGlFbmRQb2ludCA9ICcnO1xyXG4gIGlmICh0aGlzLmNvbmZpZyAmJiB0aGlzLmNvbmZpZy5hcGlFbmRQb2ludCkge1xyXG4gICAgYXBpRW5kUG9pbnQgPSB0aGlzLmNvbmZpZy5hcGlFbmRQb2ludDtcclxuICB9XHJcbiAgaWYgKGFwaUVuZFBvaW50ICE9PSAnJykge1xyXG4gICAgYXBpRW5kUG9pbnQgPSBhcGlFbmRQb2ludCArICcvJ1xyXG4gIH1cclxuICByZXR1cm4gIGFwaUVuZFBvaW50ICsgU2Vzc2lvblNlcnZpY2UuU0VTU0lPTl9BUElfQ1RYO1xyXG59XHJcblxyXG4gIGFic3RyYWN0IHBvc3RDaHVua0F1ZGlvQnVmZmVyKGF1ZGlvQnVmZmVyOiBBdWRpb0J1ZmZlciwgY2h1bmtJZHg6IG51bWJlcik6IHZvaWQ7XHJcblxyXG4gIHBvc3RBdWRpb1N0cmVhbUVuZChjaHVua0NvdW50OiBudW1iZXIpOiB2b2lkIHtcclxuXHJcbiAgICBpZih0aGlzLnJmVXVpZCkge1xyXG5cclxuICAgICAgbGV0IHNlc3Npb25zVXJsID0gdGhpcy5zZXNzaW9uc0Jhc2VVcmwoKTtcclxuICAgICAgbGV0IHJlY1VybDogc3RyaW5nID0gc2Vzc2lvbnNVcmwgKyAnLycgKyB0aGlzLnNlc3Npb24/LnNlc3Npb25JZCArICcvJyArIFJFQ0ZJTEVfQVBJX0NUWCArICcvJyArIHRoaXMucmZVdWlkKycvY29uY2F0Q2h1bmtzUmVxdWVzdCc7XHJcbiAgICAgIGxldCBmZD1uZXcgRm9ybURhdGEoKTtcclxuICAgICAgZmQuc2V0KCd1dWlkJyx0aGlzLnJmVXVpZCk7XHJcbiAgICAgIGZkLnNldCgnY2h1bmtDb3VudCcsY2h1bmtDb3VudC50b1N0cmluZygpKTtcclxuICAgICAgbGV0IHVsID0gbmV3IFVwbG9hZChmZCwgcmVjVXJsLHRoaXMuX3JlY29yZGluZ0ZpbGUpO1xyXG4gICAgICBpZih0aGlzLnVwbG9hZFNldCl7XHJcbiAgICAgICAgdGhpcy51cGxvYWRTZXQuYWRkKHVsKTtcclxuICAgICAgICB0aGlzLnVwbG9hZFNldC5jb21wbGV0ZSgpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMudXBsb2FkZXIucXVldWVVcGxvYWQodWwpO1xyXG4gICAgICAvL2NvbnNvbGUuZGVidWcoXCJRdWV1ZWQgZm9yIHVwbG9hZDogXCIrdGhpcy5fcmVjb3JkaW5nRmlsZSk7XHJcbiAgICB9ZWxzZXtcclxuICAgICAgY29uc29sZS5lcnJvcihcIlJlY29yZGluZyBmaWxlIFVVSUQgbm90IHNldCFcIilcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNsb3NlZCgpIHtcclxuICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2luZm8nO1xyXG4gICAgdGhpcy5zdGF0dXNNc2cgPSAnU2Vzc2lvbiBjbG9zZWQuJztcclxuICB9XHJcblxyXG4gIGVycm9yKG1zZz0nQW4gdW5rbm93biBlcnJvciBvY2N1cmVkIGR1cmluZyByZWNvcmRpbmcuJyxhZHZpY2U6c3RyaW5nPSdQbGVhc2UgcmV0cnkuJykge1xyXG4gICAgdGhpcy5uYXZpZ2F0aW9uRGlzYWJsZWQgPSBmYWxzZTtcclxuICAgIHRoaXMuc3RhdHVzTXNnID0gJ0VSUk9SOiBSZWNvcmRpbmcuJztcclxuICAgIHRoaXMuc3RhdHVzQWxlcnRUeXBlID0gJ2Vycm9yJztcclxuICAgIHRoaXMuZGlhbG9nLm9wZW4oTWVzc2FnZURpYWxvZywge1xyXG4gICAgICBkYXRhOiB7XHJcbiAgICAgICAgdHlwZTogJ2Vycm9yJyxcclxuICAgICAgICB0aXRsZTogJ1JlY29yZGluZyBlcnJvcicsXHJcbiAgICAgICAgbXNnOiBtc2csXHJcbiAgICAgICAgYWR2aWNlOiBhZHZpY2VcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxufVxyXG4iXX0=