speechrecorderng 3.10.13 → 3.11.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 (99) hide show
  1. package/README.md +1 -1
  2. package/fesm2022/speechrecorderng.mjs +204 -201
  3. package/fesm2022/speechrecorderng.mjs.map +1 -1
  4. package/lib/audio/ui/audio_canvas_layer_comp.d.ts +2 -2
  5. package/lib/spr.module.version.d.ts +1 -1
  6. package/lib/ui/canvas_layer_comp.d.ts +1 -1
  7. package/lib/ui/responsive_component.d.ts +1 -1
  8. package/package.json +13 -15
  9. package/esm2022/lib/action/action.mjs +0 -73
  10. package/esm2022/lib/audio/array_audio_buffer.mjs +0 -164
  11. package/esm2022/lib/audio/array_audio_buffer_input_stream.mjs +0 -86
  12. package/esm2022/lib/audio/array_audio_buffer_random_access_stream.mjs +0 -16
  13. package/esm2022/lib/audio/audio_data_holder.mjs +0 -264
  14. package/esm2022/lib/audio/audio_display.mjs +0 -118
  15. package/esm2022/lib/audio/audio_player.mjs +0 -238
  16. package/esm2022/lib/audio/capture/capture.mjs +0 -855
  17. package/esm2022/lib/audio/context.mjs +0 -79
  18. package/esm2022/lib/audio/dsp/level_measure.mjs +0 -517
  19. package/esm2022/lib/audio/format.mjs +0 -20
  20. package/esm2022/lib/audio/impl/wavformat.mjs +0 -7
  21. package/esm2022/lib/audio/impl/wavreader.mjs +0 -144
  22. package/esm2022/lib/audio/impl/wavwriter.mjs +0 -191
  23. package/esm2022/lib/audio/inddb_audio_buffer.mjs +0 -508
  24. package/esm2022/lib/audio/io/stream.mjs +0 -59
  25. package/esm2022/lib/audio/net_audio_buffer.mjs +0 -293
  26. package/esm2022/lib/audio/persistor.mjs +0 -81
  27. package/esm2022/lib/audio/playback/array_audio_buffer_source_node.mjs +0 -126
  28. package/esm2022/lib/audio/playback/audio_source_node.mjs +0 -18
  29. package/esm2022/lib/audio/playback/audio_source_worklet_module_loader.mjs +0 -167
  30. package/esm2022/lib/audio/playback/inddb_audio_buffer_source_node.mjs +0 -167
  31. package/esm2022/lib/audio/playback/net_audio_buffer_source_node.mjs +0 -218
  32. package/esm2022/lib/audio/playback/player.mjs +0 -402
  33. package/esm2022/lib/audio/ui/audio_canvas_layer_comp.mjs +0 -347
  34. package/esm2022/lib/audio/ui/audio_display_control.mjs +0 -150
  35. package/esm2022/lib/audio/ui/audio_display_scroll_pane.mjs +0 -146
  36. package/esm2022/lib/audio/ui/audiosignal.mjs +0 -533
  37. package/esm2022/lib/audio/ui/common.mjs +0 -19
  38. package/esm2022/lib/audio/ui/container.mjs +0 -414
  39. package/esm2022/lib/audio/ui/livelevel.mjs +0 -361
  40. package/esm2022/lib/audio/ui/scroll_pane_horizontal.mjs +0 -11
  41. package/esm2022/lib/audio/ui/sonagram.mjs +0 -900
  42. package/esm2022/lib/db/inddb.mjs +0 -120
  43. package/esm2022/lib/dsp/utils.mjs +0 -48
  44. package/esm2022/lib/environment/environment.defaults.mjs +0 -9
  45. package/esm2022/lib/io/BinaryReader.mjs +0 -93
  46. package/esm2022/lib/io/BinaryWriter.mjs +0 -80
  47. package/esm2022/lib/io/stream.mjs +0 -259
  48. package/esm2022/lib/math/2d/geometry.mjs +0 -28
  49. package/esm2022/lib/math/complex.mjs +0 -58
  50. package/esm2022/lib/math/dft.mjs +0 -196
  51. package/esm2022/lib/media/utils.mjs +0 -14
  52. package/esm2022/lib/net/uploader.mjs +0 -367
  53. package/esm2022/lib/recorder_component.mjs +0 -65
  54. package/esm2022/lib/speechrecorder/project/project.mjs +0 -54
  55. package/esm2022/lib/speechrecorder/project/project.service.mjs +0 -64
  56. package/esm2022/lib/speechrecorder/recording.mjs +0 -124
  57. package/esm2022/lib/speechrecorder/recordings/basic_recording.service.mjs +0 -221
  58. package/esm2022/lib/speechrecorder/recordings/recordings.service.mjs +0 -1014
  59. package/esm2022/lib/speechrecorder/script/script.mjs +0 -114
  60. package/esm2022/lib/speechrecorder/script/script.service.mjs +0 -47
  61. package/esm2022/lib/speechrecorder/session/audiorecorder.mjs +0 -1179
  62. package/esm2022/lib/speechrecorder/session/basicrecorder.mjs +0 -676
  63. package/esm2022/lib/speechrecorder/session/controlpanel.mjs +0 -416
  64. package/esm2022/lib/speechrecorder/session/item.mjs +0 -30
  65. package/esm2022/lib/speechrecorder/session/progress.mjs +0 -135
  66. package/esm2022/lib/speechrecorder/session/prompting.mjs +0 -639
  67. package/esm2022/lib/speechrecorder/session/recorder_combi_pane.mjs +0 -88
  68. package/esm2022/lib/speechrecorder/session/recording_file_cache.mjs +0 -195
  69. package/esm2022/lib/speechrecorder/session/recording_list.mjs +0 -188
  70. package/esm2022/lib/speechrecorder/session/recordingfile/recording-file-meta.component.mjs +0 -128
  71. package/esm2022/lib/speechrecorder/session/recordingfile/recording-file-navi.component.mjs +0 -114
  72. package/esm2022/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.mjs +0 -146
  73. package/esm2022/lib/speechrecorder/session/recordingfile/recording-file-view.component.mjs +0 -424
  74. package/esm2022/lib/speechrecorder/session/recordingfile/recording-file.mjs +0 -68
  75. package/esm2022/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +0 -288
  76. package/esm2022/lib/speechrecorder/session/session.mjs +0 -2
  77. package/esm2022/lib/speechrecorder/session/session.service.mjs +0 -69
  78. package/esm2022/lib/speechrecorder/session/session_finished_dialog.mjs +0 -46
  79. package/esm2022/lib/speechrecorder/session/sessionmanager.mjs +0 -1385
  80. package/esm2022/lib/speechrecorder/session/warning_bar.mjs +0 -33
  81. package/esm2022/lib/speechrecorder/spruploader.mjs +0 -22
  82. package/esm2022/lib/speechrecorder/startstopsignal/startstopsignal.mjs +0 -2
  83. package/esm2022/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.mjs +0 -57
  84. package/esm2022/lib/speechrecorderng.component.mjs +0 -392
  85. package/esm2022/lib/speechrecorderng.module.mjs +0 -97
  86. package/esm2022/lib/spr.config.mjs +0 -27
  87. package/esm2022/lib/spr.module.version.mjs +0 -2
  88. package/esm2022/lib/ui/canvas_layer_comp.mjs +0 -38
  89. package/esm2022/lib/ui/intersection-observer.directive.mjs +0 -32
  90. package/esm2022/lib/ui/message_dialog.mjs +0 -51
  91. package/esm2022/lib/ui/recordingitem_display.mjs +0 -253
  92. package/esm2022/lib/ui/responsive_component.mjs +0 -24
  93. package/esm2022/lib/utils/scrollIntoViewToBottom.mjs +0 -23
  94. package/esm2022/lib/utils/ua-parser.mjs +0 -190
  95. package/esm2022/lib/utils/utils.mjs +0 -132
  96. package/esm2022/lib/utils/wake_lock.mjs +0 -114
  97. package/esm2022/lib/utils/wake_lock_media.mjs +0 -2
  98. package/esm2022/public-api.mjs +0 -35
  99. package/esm2022/speechrecorderng.mjs +0 -5
@@ -1,508 +0,0 @@
1
- import { Observable } from "rxjs";
2
- import { UUID } from "../utils/utils";
3
- import { BasicAudioSource } from "./audio_data_holder";
4
- export class PersistentAudioStorageTarget {
5
- get indexedDb() {
6
- return this._indexedDb;
7
- }
8
- get storeName() {
9
- return this._storeName;
10
- }
11
- constructor(_indexedDb, _storeName) {
12
- this._indexedDb = _indexedDb;
13
- this._storeName = _storeName;
14
- }
15
- transaction(mode) {
16
- return this._indexedDb.transaction(this.storeName, mode);
17
- }
18
- objectStore(mode) {
19
- let tr = this.transaction(mode);
20
- return tr.objectStore(this._storeName);
21
- }
22
- deleteAll() {
23
- return new Observable(subscriber => {
24
- let os = this.objectStore('readwrite');
25
- let clearReq = os.clear();
26
- clearReq.onsuccess = () => {
27
- console.debug("Cleared audio storage object store.");
28
- os.transaction.commit();
29
- };
30
- clearReq.onerror = () => {
31
- os.transaction.abort();
32
- console.error("Could not clear object store: " + clearReq.error);
33
- };
34
- os.transaction.oncomplete = () => {
35
- console.debug("Transaction complete: Clear audio storage object store.");
36
- subscriber.complete();
37
- };
38
- os.transaction.onerror = (err) => {
39
- subscriber.error(err);
40
- };
41
- });
42
- }
43
- }
44
- export class IndexedDbAudioBuffer extends BasicAudioSource {
45
- get chunkFrameLen() {
46
- return this._chunkFrameLen;
47
- }
48
- get persistentAudioStorageTarget() {
49
- return this._persistentAudioStorageTarget;
50
- }
51
- get uuid() {
52
- return this._uuid;
53
- }
54
- constructor(_persistentAudioStorageTarget, _channelCount, _sampleRate, _chunkFrameLen, _frameLen, _uuid) {
55
- super();
56
- this._persistentAudioStorageTarget = _persistentAudioStorageTarget;
57
- this._channelCount = _channelCount;
58
- this._sampleRate = _sampleRate;
59
- this._chunkFrameLen = _chunkFrameLen;
60
- this._frameLen = _frameLen;
61
- this._uuid = _uuid;
62
- this._chunkCount = 0;
63
- this.indDbChkIdx = 0;
64
- this._sealed = false;
65
- this._storeError = null;
66
- this.ready();
67
- }
68
- get channelCount() {
69
- return this._channelCount;
70
- }
71
- sealed() {
72
- return this._sealed;
73
- }
74
- seal() {
75
- this._sealed = true;
76
- }
77
- deleteChunk(os, ci, cb, errCb) {
78
- // Build bounds for channels
79
- let lIdx = [this._uuid, ci, 0];
80
- let hIdx = [this._uuid, ci, this._channelCount];
81
- let chsKr = IDBKeyRange.bound(lIdx, hIdx);
82
- let exRq = os.getAllKeys(chsKr);
83
- exRq.onsuccess = () => {
84
- let cc = exRq.result;
85
- if (cc && cc.length > 0) {
86
- let rq = os.delete(chsKr);
87
- rq.onerror = (errEv) => {
88
- errCb(new Error(errEv.toString()));
89
- };
90
- os.transaction.oncomplete = () => {
91
- cb(cc);
92
- };
93
- os.transaction.commit();
94
- }
95
- };
96
- exRq.onerror = (errEv) => {
97
- errCb(new Error(errEv.toString()));
98
- };
99
- }
100
- deleteAllBufs(os, ci, cbEnd, cbErr) {
101
- //console.debug('IndexedDbAudioBuffer::fillBufs: framePos:'+framePos+', frameLen: '+frameLen+', filled: '+filled+', srcFramePos: '+srcFramePos+',ci: '+ci+', ccPos: '+ccPos);
102
- this.deleteChunk(os, ci, (ccKeys) => {
103
- if (ccKeys && ccKeys.length > 0) {
104
- //console.debug('IndexedDbAudioBuffer::fillBufs frameLen: '+frameLen);
105
- ci++;
106
- this.deleteAllBufs(os, ci, cbEnd, cbErr);
107
- }
108
- else {
109
- //console.debug('IndexedDbAudioBuffer::fillBufs (chunk not found) call: cbend '+filled);
110
- cbEnd();
111
- }
112
- }, (err) => {
113
- cbErr(err);
114
- });
115
- }
116
- get sampleRate() {
117
- return this._sampleRate;
118
- }
119
- get frameLen() {
120
- return this._frameLen;
121
- }
122
- get chunkCount() {
123
- return this._chunkCount;
124
- }
125
- appendRawAudioData(data) {
126
- return new Observable(subscriber => {
127
- if (this._persistentAudioStorageTarget && this._uuid) {
128
- let tr = this._persistentAudioStorageTarget.indexedDb.transaction(this._persistentAudioStorageTarget.storeName, 'readwrite');
129
- let recFileObjStore = tr.objectStore(this._persistentAudioStorageTarget.storeName);
130
- try {
131
- let ch0Data = data[0];
132
- let dataChkCnt = ch0Data.length;
133
- let pos = 0;
134
- for (let chCkIdx = 0; chCkIdx < dataChkCnt; chCkIdx++) {
135
- let bufLen = 0;
136
- for (let ch = 0; ch < this.channelCount; ch++) {
137
- let chChk = data[ch][chCkIdx];
138
- bufLen = chChk.length;
139
- //let cacheId = uuid + '_' + ch + '_' + chCkIdx;
140
- let chkDbId = [this._uuid, this.indDbChkIdx + chCkIdx, ch];
141
- let cr = recFileObjStore.add(chChk, chkDbId);
142
- //console.debug("Added: "+ch+" "+(this.indDbChkIdx+chCkIdx));
143
- cr.onsuccess = () => {
144
- //console.debug("Stored audio data to indexed db");
145
- // if(chCkIdx>= dataChkCnt-1 && ch>=this.channelCount-1){
146
- // tr.commit();
147
- // }
148
- };
149
- cr.onerror = () => {
150
- if (!this._storeError) {
151
- // Only log the first error
152
- console.error("Error storing audio data of " + chChk.byteLength + " bytes to indexed db: " + cr.error);
153
- }
154
- };
155
- }
156
- pos += bufLen;
157
- this._frameLen += bufLen;
158
- }
159
- this.indDbChkIdx += dataChkCnt;
160
- tr.onerror = (ev) => {
161
- if (!this._storeError) {
162
- // Only log the first error
163
- console.error("Failed to store audio data to indexed db, transaction error: " + tr.error);
164
- this._storeError = tr.error;
165
- }
166
- subscriber.error(tr.error);
167
- };
168
- tr.onabort = (ev) => {
169
- // If Chrome reaches quota it aborts the transaction
170
- if (!this._storeError) {
171
- // Only log the first error
172
- console.error("Failed to store audio data to indexed db, transaction aborted: " + tr.error);
173
- this._storeError = tr.error;
174
- }
175
- subscriber.error(tr.error);
176
- };
177
- tr.oncomplete = (ev) => {
178
- subscriber.complete();
179
- };
180
- tr.commit();
181
- }
182
- catch (err) {
183
- subscriber.error(new Error('Transfer audio data error: ' + err));
184
- }
185
- }
186
- });
187
- }
188
- static fromChunkAudioBuffer(persistentAudioStorageTarget, audioBuffer) {
189
- return new Observable(subscriber => {
190
- let chs = audioBuffer.numberOfChannels;
191
- let sr = audioBuffer.sampleRate;
192
- let chkFrameLength = audioBuffer.length;
193
- let iab = new IndexedDbAudioBuffer(persistentAudioStorageTarget, chs, sr, chkFrameLength, 0, UUID.generate());
194
- iab.appendChunkAudioBuffer(audioBuffer).subscribe({
195
- next: () => {
196
- subscriber.next(iab);
197
- },
198
- complete: () => {
199
- subscriber.complete();
200
- },
201
- error: (err) => {
202
- subscriber.error(err);
203
- }
204
- });
205
- });
206
- }
207
- appendChunkAudioBuffer(audioBuffer) {
208
- if (this._sealed) {
209
- throw new Error('Cannot append audio buffer to already sealed audio buffer.');
210
- }
211
- let chs = audioBuffer.numberOfChannels;
212
- if (this._channelCount !== chs) {
213
- throw new Error('Cannot append audio buffer with ' + chs + ' channels to this array audio buffer with ' + this._channelCount + ' channels. Number of channels must match.');
214
- }
215
- let sr = audioBuffer.sampleRate;
216
- if (sr !== this._sampleRate) {
217
- throw new Error('Cannot append audio buffer with samplerate ' + sr + ' to this array audio buffer with samplerate ' + this._sampleRate + '. Samplerates must match.');
218
- }
219
- let abFl = audioBuffer.length;
220
- if (abFl > this._chunkFrameLen) {
221
- throw new Error('Cannot append audio buffer with frame length ' + abFl + ' to this array audio buffer with chunk frame length ' + this._chunkFrameLen + '. Chunk length must be equal or less if last chunk.');
222
- }
223
- return new Observable(subscriber => {
224
- if (this._persistentAudioStorageTarget && this._uuid) {
225
- let tr = this._persistentAudioStorageTarget.transaction('readwrite');
226
- let recFileObjStore = tr.objectStore(this._persistentAudioStorageTarget.storeName);
227
- try {
228
- for (let ch = 0; ch < this.channelCount; ch++) {
229
- let chChk = audioBuffer.getChannelData(ch);
230
- let chkDbId = [this._uuid, this.indDbChkIdx++, ch];
231
- try {
232
- let cr = recFileObjStore.add(chChk, chkDbId);
233
- cr.onsuccess = (ev) => { };
234
- cr.onerror = (ev) => {
235
- // iPad may throw QuotaExceededError here
236
- // iPad asks for more storage and if denied, the error is thrown here
237
- if (!this._storeError) {
238
- // Only log the first error
239
- console.error("Error storing audio data of " + chChk.byteLength + " bytes to indexed db: " + cr.error);
240
- }
241
- //subscriber.error(cr.error);
242
- };
243
- }
244
- catch (err1) {
245
- if (!this._storeError) {
246
- console.error("Error adding audio data to indexed db store: " + err1);
247
- this._storeError = (err1 instanceof Error) ? err1 : new Error(err1);
248
- }
249
- subscriber.error(err1);
250
- }
251
- }
252
- this._frameLen += abFl;
253
- tr.onerror = (ev) => {
254
- if (!this._storeError) {
255
- // Only log the first error
256
- console.error("Failed to store audio data to indexed db, transaction error: " + tr.error);
257
- this._storeError = tr.error;
258
- }
259
- subscriber.error(tr.error);
260
- };
261
- tr.onabort = (ev) => {
262
- // If Chrome reaches quota it aborts the transaction
263
- if (!this._storeError) {
264
- // Only log the first error
265
- console.error("Failed to store audio data to indexed db, transaction aborted: " + tr.error);
266
- this._storeError = tr.error;
267
- }
268
- subscriber.error(tr.error);
269
- };
270
- tr.oncomplete = (ev) => {
271
- //console.debug("Transaction complete");
272
- if (abFl < this._chunkFrameLen) {
273
- // last chunk
274
- this.seal();
275
- }
276
- subscriber.next();
277
- subscriber.complete();
278
- };
279
- tr.commit();
280
- }
281
- catch (err) {
282
- console.error('Catched error: ' + err);
283
- subscriber.error(new Error('Transfer audio data error: ' + err));
284
- }
285
- }
286
- });
287
- }
288
- releaseAudioData() {
289
- return new Observable((subscriber) => {
290
- let os = this._persistentAudioStorageTarget.objectStore('readwrite');
291
- this.deleteAllBufs(os, 0, () => {
292
- subscriber.next();
293
- subscriber.complete();
294
- }, (err) => {
295
- subscriber.error(err);
296
- });
297
- });
298
- }
299
- toString() {
300
- return "Indexed db audio buffer. Channels: " + this.channelCount + ", sample rate: " + this.sampleRate + ", chunk frame length: " + this._chunkFrameLen + ", number of chunks: " + this.chunkCount + ", frame length: " + this.frameLen + ", sealed: " + this.sealed();
301
- }
302
- asyncAudioInputStream() {
303
- return new IndexedDbAudioInputStream(this);
304
- }
305
- audioInputStream() {
306
- // Synchronous stream not supported
307
- return null;
308
- }
309
- get duration() {
310
- return this._chunkFrameLen / this._sampleRate;
311
- }
312
- get numberOfChannels() {
313
- return this._channelCount;
314
- }
315
- sampleCounts() {
316
- return this._channelCount * this._frameLen;
317
- }
318
- randomAccessAudioStream() {
319
- return new IndexedDbRandomAccessStream(this);
320
- }
321
- }
322
- export class IndexedDbRandomAccessStream {
323
- constructor(_inddbAb) {
324
- this._inddbAb = _inddbAb;
325
- this._currCi = 0;
326
- this._ccCache = null;
327
- }
328
- chunk(os, ci, cb, errCb) {
329
- // Build bounds for channels
330
- let lIdx = [this._inddbAb.uuid, ci, 0];
331
- let hIdx = [this._inddbAb.uuid, ci, this._inddbAb.channelCount];
332
- let chsKr = IDBKeyRange.bound(lIdx, hIdx);
333
- let rq = os.getAll(chsKr);
334
- rq.onsuccess = () => {
335
- let cc = rq.result;
336
- let cc0;
337
- let ccChs = cc.length;
338
- if (ccChs == 0) {
339
- cb(null);
340
- return;
341
- }
342
- if (ccChs !== this._inddbAb.channelCount) {
343
- errCb(new Error('Number of channels of inddb data (' + ccChs + ') does not match number of channels (' + this._inddbAb.channelCount + ')'));
344
- return;
345
- }
346
- if (cc.length > 0) {
347
- cc0 = cc[0];
348
- }
349
- let arrBuf = new Array();
350
- let ccLen = cc0.length;
351
- for (let ch = 0; ch < ccChs; ch++) {
352
- let chArr = new Float32Array(ccLen);
353
- for (let si = 0; si < ccLen; si++) {
354
- chArr[si] = cc[ch][si];
355
- }
356
- arrBuf.push(chArr);
357
- }
358
- cb(arrBuf);
359
- };
360
- rq.onerror = (errEv) => {
361
- errCb(new Error(errEv.toString()));
362
- };
363
- }
364
- _fillBufs(ccBufs, trgState, srcState) {
365
- let ccBufsChs = ccBufs.length;
366
- if (ccBufsChs > 0) {
367
- let ccBuf0 = ccBufs[0];
368
- let ccBufsLen = ccBuf0.length;
369
- //console.debug('IndexedDbAudioBuffer::fillBufs framePos: '+framePos+', srcFramePos: '+srcFramePos+', ccBufsLen: '+ccBufsLen);
370
- if (trgState.framePos >= srcState.srcFramePos + ccBufsLen) {
371
- // target frame position is ahead, seek to next source buffer
372
- //console.debug('IndexedDbAudioBuffer::fillBufs seek to next inddb buffer');
373
- this._ccCache = null;
374
- srcState.ci++;
375
- srcState.ccPos = 0;
376
- srcState.srcFramePos += ccBufsLen;
377
- }
378
- else {
379
- // Assuming target frame pos is inside current source buffer
380
- srcState.ccPos = trgState.framePos - srcState.srcFramePos;
381
- let ccAvail = ccBufsLen - srcState.ccPos;
382
- let toCopy = ccBufsLen;
383
- if (toCopy > ccAvail) {
384
- toCopy = ccAvail;
385
- }
386
- if (toCopy > trgState.frameLen) {
387
- toCopy = trgState.frameLen;
388
- }
389
- for (let ch = 0; ch < ccBufsChs; ch++) {
390
- for (let si = 0; si < toCopy; si++) {
391
- trgState.trgBufs[ch][trgState.filled + si] = ccBufs[ch][srcState.ccPos + si];
392
- }
393
- }
394
- trgState.filled += toCopy;
395
- trgState.frameLen -= toCopy;
396
- trgState.framePos += toCopy;
397
- srcState.ccPos += toCopy;
398
- if (srcState.ccPos >= ccBufsLen) {
399
- // Invalidate cache
400
- this._ccCache = null;
401
- srcState.ci++;
402
- this._currCi = srcState.ci;
403
- srcState.ccPos = 0;
404
- srcState.srcFramePos += ccBufsLen;
405
- }
406
- }
407
- }
408
- }
409
- fillBufs(os, trgState, srcState, cb, cbEnd, cbErr) {
410
- //console.debug('IndexedDbAudioBuffer::fillBufs: framePos:'+trgState.framePos+', frameLen: '+trgState.frameLen+', filled: '+trgState.filled+', srcFramePos: '+srcState.srcFramePos+',ci: '+srcState.ci+', ccPos: '+srcState.ccPos);
411
- if (this._ccCache) {
412
- this._fillBufs(this._ccCache, trgState, srcState);
413
- //console.debug('IndexedDbAudioBuffer::fillBufs frameLen: '+trgState.frameLen);
414
- if (trgState.frameLen === 0) {
415
- //console.debug('IndexedDbAudioBuffer::fillBufs (framelen==0) call: cbend '+trgState.filled);
416
- cbEnd(trgState.filled);
417
- }
418
- else {
419
- this.fillBufs(os, trgState, srcState, cb, cbEnd, cbErr);
420
- }
421
- }
422
- else {
423
- this.chunk(os, srcState.ci, (ccBufs) => {
424
- if (ccBufs) {
425
- this._currCi = srcState.ci;
426
- this._ccCache = ccBufs;
427
- this._fillBufs(ccBufs, trgState, srcState);
428
- //console.debug('IndexedDbAudioBuffer::fillBufs frameLen: '+trgState.frameLen);
429
- if (trgState.frameLen === 0) {
430
- //console.debug('IndexedDbAudioBuffer::fillBufs (framelen==0) call: cbend '+trgState.filled);
431
- cbEnd(trgState.filled);
432
- }
433
- else {
434
- this.fillBufs(os, trgState, srcState, cb, cbEnd, cbErr);
435
- }
436
- }
437
- else {
438
- //console.debug('IndexedDbAudioBuffer::fillBufs (chunk not found) call: cbend '+trgState.filled);
439
- cbEnd(trgState.filled);
440
- }
441
- }, (err) => {
442
- cbErr(err);
443
- });
444
- }
445
- }
446
- framesObs(framePos, frameLen, bufs) {
447
- return new Observable((subscriber) => {
448
- let tr = this._inddbAb.persistentAudioStorageTarget.transaction();
449
- let os = tr.objectStore(this._inddbAb.persistentAudioStorageTarget.storeName);
450
- // Positioning
451
- let newCi = Math.floor(framePos / this._inddbAb.chunkFrameLen);
452
- if (newCi !== this._currCi) {
453
- this._currCi = newCi;
454
- this._ccCache = null;
455
- }
456
- let srcFramePos = newCi * this._inddbAb.chunkFrameLen;
457
- let trgState = { framePos: framePos, frameLen: frameLen, trgBufs: bufs, filled: 0 };
458
- let srcState = { srcFramePos: srcFramePos, ci: newCi, ccPos: 0, ccFilled: 0 };
459
- this.fillBufs(os, trgState, srcState, (val) => { }, (filled) => {
460
- subscriber.next(filled);
461
- subscriber.complete();
462
- }, err => {
463
- subscriber.error(err);
464
- });
465
- });
466
- }
467
- close() {
468
- this._currCi = 0;
469
- this._ccCache = null;
470
- }
471
- }
472
- export class IndexedDbAudioInputStream {
473
- constructor(inddbAb) {
474
- this.inddbAb = inddbAb;
475
- this.framePos = 0;
476
- this.inddbAbStr = new IndexedDbRandomAccessStream(inddbAb);
477
- }
478
- close() {
479
- this.inddbAbStr.close();
480
- }
481
- readObs(buffers) {
482
- return new Observable(subscr => {
483
- if (buffers && buffers.length > 0) {
484
- let fl = buffers[0].length;
485
- this.inddbAbStr.framesObs(this.framePos, fl, buffers).subscribe({
486
- next: (read) => {
487
- this.framePos += read;
488
- subscr.next(read);
489
- },
490
- complete: () => {
491
- subscr.complete();
492
- },
493
- error: (err) => {
494
- subscr.error(err);
495
- }
496
- });
497
- }
498
- else {
499
- subscr.next(0);
500
- subscr.complete();
501
- }
502
- });
503
- }
504
- skipFrames(n) {
505
- this.framePos += n;
506
- }
507
- }
508
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZGJfYXVkaW9fYnVmZmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc3BlZWNocmVjb3JkZXJuZy9zcmMvbGliL2F1ZGlvL2luZGRiX2F1ZGlvX2J1ZmZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBRWhDLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwQyxPQUFPLEVBQWMsZ0JBQWdCLEVBQTBCLE1BQU0scUJBQXFCLENBQUM7QUFFM0YsTUFBTSxPQUFPLDRCQUE0QjtJQUN2QyxJQUFJLFNBQVM7UUFDWCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDekIsQ0FBQztJQUVELElBQUksU0FBUztRQUNYLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUN6QixDQUFDO0lBQ0QsWUFBb0IsVUFBc0IsRUFBUyxVQUFpQjtRQUFoRCxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBQVMsZUFBVSxHQUFWLFVBQVUsQ0FBTztJQUNwRSxDQUFDO0lBRUQsV0FBVyxDQUFDLElBQXdCO1FBQ2xDLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRUQsV0FBVyxDQUFDLElBQXdCO1FBQ2xDLElBQUksRUFBRSxHQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDOUIsT0FBTyxFQUFFLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBRUQsU0FBUztRQUNQLE9BQU8sSUFBSSxVQUFVLENBQU8sVUFBVSxDQUFDLEVBQUU7WUFDdkMsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN2QyxJQUFJLFFB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Q0YsQ0FBQyxDQUFBO1lBQ0osQ0FBQztpQkFBSSxDQUFDO2dCQUNKLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2YsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3BCLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxVQUFVLENBQUMsQ0FBUztRQUNsQixJQUFJLENBQUMsUUFBUSxJQUFFLENBQUMsQ0FBQztJQUNuQixDQUFDO0NBRUYiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge09ic2VydmFibGV9IGZyb20gXCJyeGpzXCI7XHJcbmltcG9ydCB7QXN5bmNGbG9hdDMyQXJyYXlJbnB1dFN0cmVhbSwgRmxvYXQzMkFycmF5SW5wdXRTdHJlYW19IGZyb20gXCIuLi9pby9zdHJlYW1cIjtcclxuaW1wb3J0IHtVVUlEfSBmcm9tIFwiLi4vdXRpbHMvdXRpbHNcIjtcclxuaW1wb3J0IHtBdWRpb1NvdXJjZSwgQmFzaWNBdWRpb1NvdXJjZSwgUmFuZG9tQWNjZXNzQXVkaW9TdHJlYW19IGZyb20gXCIuL2F1ZGlvX2RhdGFfaG9sZGVyXCI7XHJcblxyXG5leHBvcnQgY2xhc3MgUGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldHtcclxuICBnZXQgaW5kZXhlZERiKCk6IElEQkRhdGFiYXNlIHtcclxuICAgIHJldHVybiB0aGlzLl9pbmRleGVkRGI7XHJcbiAgfVxyXG5cclxuICBnZXQgc3RvcmVOYW1lKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5fc3RvcmVOYW1lO1xyXG4gIH1cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9pbmRleGVkRGI6SURCRGF0YWJhc2UscHJpdmF0ZSBfc3RvcmVOYW1lOnN0cmluZykge1xyXG4gIH1cclxuXHJcbiAgdHJhbnNhY3Rpb24obW9kZT86SURCVHJhbnNhY3Rpb25Nb2RlKTpJREJUcmFuc2FjdGlvbntcclxuICAgIHJldHVybiB0aGlzLl9pbmRleGVkRGIudHJhbnNhY3Rpb24odGhpcy5zdG9yZU5hbWUsIG1vZGUpO1xyXG4gIH1cclxuXHJcbiAgb2JqZWN0U3RvcmUobW9kZT86SURCVHJhbnNhY3Rpb25Nb2RlICl7XHJcbiAgICBsZXQgdHI9dGhpcy50cmFuc2FjdGlvbihtb2RlKTtcclxuICAgIHJldHVybiB0ci5vYmplY3RTdG9yZSh0aGlzLl9zdG9yZU5hbWUpO1xyXG4gIH1cclxuXHJcbiAgZGVsZXRlQWxsKCk6T2JzZXJ2YWJsZTx2b2lkPntcclxuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZTx2b2lkPihzdWJzY3JpYmVyID0+IHtcclxuICAgICAgbGV0IG9zID0gdGhpcy5vYmplY3RTdG9yZSgncmVhZHdyaXRlJyk7XHJcbiAgICAgIGxldCBjbGVhclJlcT1vcy5jbGVhcigpO1xyXG4gICAgICBjbGVhclJlcS5vbnN1Y2Nlc3M9KCk9PntcclxuICAgICAgICBjb25zb2xlLmRlYnVnKFwiQ2xlYXJlZCBhdWRpbyBzdG9yYWdlIG9iamVjdCBzdG9yZS5cIik7XHJcbiAgICAgICAgb3MudHJhbnNhY3Rpb24uY29tbWl0KCk7XHJcbiAgICAgIH1cclxuICAgICAgY2xlYXJSZXEub25lcnJvcj0oKT0+e1xyXG4gICAgICAgIG9zLnRyYW5zYWN0aW9uLmFib3J0KCk7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkNvdWxkIG5vdCBjbGVhciBvYmplY3Qgc3RvcmU6IFwiK2NsZWFyUmVxLmVycm9yKTtcclxuICAgICAgfVxyXG4gICAgICBvcy50cmFuc2FjdGlvbi5vbmNvbXBsZXRlID0gKCkgPT4ge1xyXG4gICAgICAgIGNvbnNvbGUuZGVidWcoXCJUcmFuc2FjdGlvbiBjb21wbGV0ZTogQ2xlYXIgYXVkaW8gc3RvcmFnZSBvYmplY3Qgc3RvcmUuXCIpO1xyXG4gICAgICAgICAgc3Vic2NyaWJlci5jb21wbGV0ZSgpO1xyXG4gICAgICB9XHJcbiAgICAgIG9zLnRyYW5zYWN0aW9uLm9uZXJyb3IgPSAoZXJyKSA9PiB7XHJcbiAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKGVycik7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBJbmRleGVkRGJBdWRpb0J1ZmZlciBleHRlbmRzIEJhc2ljQXVkaW9Tb3VyY2UgaW1wbGVtZW50cyBBdWRpb1NvdXJjZXtcclxuICBnZXQgY2h1bmtGcmFtZUxlbigpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX2NodW5rRnJhbWVMZW47XHJcbiAgfVxyXG4gIGdldCBwZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0KCk6IFBlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQge1xyXG4gICAgcmV0dXJuIHRoaXMuX3BlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQ7XHJcbiAgfVxyXG4gIGdldCB1dWlkKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5fdXVpZDtcclxuICB9XHJcblxyXG5cclxuICBwcml2YXRlIF9jaHVua0NvdW50PTA7XHJcbiAgcHJpdmF0ZSBpbmREYkNoa0lkeDogbnVtYmVyPTA7XHJcbiAgcHJpdmF0ZSBfc2VhbGVkPWZhbHNlO1xyXG4gIHByaXZhdGUgX3N0b3JlRXJyb3I6RXJyb3J8bnVsbD1udWxsO1xyXG5cclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfcGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldDpQZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0LHByaXZhdGUgX2NoYW5uZWxDb3VudDogbnVtYmVyLCBwcml2YXRlIF9zYW1wbGVSYXRlOiBudW1iZXIscHJpdmF0ZSBfY2h1bmtGcmFtZUxlbjpudW1iZXIscHJpdmF0ZSBfZnJhbWVMZW46bnVtYmVyLCBwcml2YXRlIF91dWlkOnN0cmluZykge1xyXG4gICAgc3VwZXIoKTtcclxuICAgIHRoaXMucmVhZHkoKTtcclxuICB9XHJcblxyXG4gIGdldCBjaGFubmVsQ291bnQoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLl9jaGFubmVsQ291bnQ7XHJcbiAgfVxyXG5cclxuICBzZWFsZWQoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5fc2VhbGVkO1xyXG4gIH1cclxuXHJcbiAgc2VhbCgpOnZvaWR7XHJcbiAgICB0aGlzLl9zZWFsZWQ9dHJ1ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZGVsZXRlQ2h1bmsob3M6SURCT2JqZWN0U3RvcmUsY2k6bnVtYmVyLGNiOihrZXlzOklEQlZhbGlkS2V5W10pPT52b2lkLGVyckNiOihlcnI6RXJyb3IpPT52b2lkKXtcclxuXHJcbiAgICAvLyBCdWlsZCBib3VuZHMgZm9yIGNoYW5uZWxzXHJcbiAgICBsZXQgbElkeD1bdGhpcy5fdXVpZCxjaSwwXTtcclxuICAgIGxldCBoSWR4PVt0aGlzLl91dWlkLGNpLHRoaXMuX2NoYW5uZWxDb3VudF07XHJcbiAgICBsZXQgY2hzS3I9SURCS2V5UmFuZ2UuYm91bmQobElkeCxoSWR4KTtcclxuXHJcbiAgICBsZXQgZXhScT1vcy5nZXRBbGxLZXlzKGNoc0tyKTtcclxuXHJcbiAgICBleFJxLm9uc3VjY2Vzcz0oKT0+e1xyXG4gICAgICBsZXQgY2M9ZXhScS5yZXN1bHQ7XHJcbiAgICAgIGlmKGNjICYmIGNjLmxlbmd0aD4wKSB7XHJcbiAgICAgICAgbGV0IHJxID0gb3MuZGVsZXRlKGNoc0tyKTtcclxuICAgICAgICBycS5vbmVycm9yPShlcnJFdik9PntcclxuICAgICAgICAgIGVyckNiKG5ldyBFcnJvcihlcnJFdi50b1N0cmluZygpKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIG9zLnRyYW5zYWN0aW9uLm9uY29tcGxldGU9KCk9PntcclxuICAgICAgICAgIGNiKGNjKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgb3MudHJhbnNhY3Rpb24uY29tbWl0KCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGV4UnEub25lcnJvcj0oZXJyRXYpPT57XHJcbiAgICAgIGVyckNiKG5ldyBFcnJvcihlcnJFdi50b1N0cmluZygpKSk7XHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBkZWxldGVBbGxCdWZzKG9zOklEQk9iamVjdFN0b3JlLGNpOm51bWJlcixjYkVuZDooKT0+dm9pZCxjYkVycjooZXJyOkVycm9yKT0+dm9pZCl7XHJcbiAgICAvL2NvbnNvbGUuZGVidWcoJ0luZGV4ZWREYkF1ZGlvQnVmZmVyOjpmaWxsQnVmczogZnJhbWVQb3M6JytmcmFtZVBvcysnLCBmcmFtZUxlbjogJytmcmFtZUxlbisnLCBmaWxsZWQ6ICcrZmlsbGVkKycsIHNyY0ZyYW1lUG9zOiAnK3NyY0ZyYW1lUG9zKycsY2k6ICcrY2krJywgY2NQb3M6ICcrY2NQb3MpO1xyXG4gICAgdGhpcy5kZWxldGVDaHVuayhvcyxjaSwoY2NLZXlzKT0+e1xyXG4gICAgICBpZihjY0tleXMgJiYgY2NLZXlzLmxlbmd0aD4wKXtcclxuICAgICAgICAvL2NvbnNvbGUuZGVidWcoJ0luZGV4ZWREYkF1ZGlvQnVmZmVyOjpmaWxsQnVmcyBmcmFtZUxlbjogJytmcmFtZUxlbik7XHJcbiAgICAgICAgY2krKztcclxuICAgICAgICB0aGlzLmRlbGV0ZUFsbEJ1ZnMob3MsY2ksY2JFbmQsIGNiRXJyKTtcclxuICAgICAgfWVsc2V7XHJcbiAgICAgICAgLy9jb25zb2xlLmRlYnVnKCdJbmRleGVkRGJBdWRpb0J1ZmZlcjo6ZmlsbEJ1ZnMgKGNodW5rIG5vdCBmb3VuZCkgY2FsbDogY2JlbmQgJytmaWxsZWQpO1xyXG4gICAgICAgIGNiRW5kKCk7XHJcbiAgICAgIH1cclxuICAgIH0sKGVycik9PntcclxuICAgICAgY2JFcnIoZXJyKTtcclxuICAgIH0pO1xyXG5cclxuICB9XHJcblxyXG4gIGdldCBzYW1wbGVSYXRlKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gdGhpcy5fc2FtcGxlUmF0ZTtcclxuICB9XHJcblxyXG4gIGdldCBmcmFtZUxlbigpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX2ZyYW1lTGVuO1xyXG4gIH1cclxuXHJcbiAgZ2V0IGNodW5rQ291bnQoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLl9jaHVua0NvdW50O1xyXG4gIH1cclxuXHJcbiAgYXBwZW5kUmF3QXVkaW9EYXRhKGRhdGE6QXJyYXk8QXJyYXk8RmxvYXQzMkFycmF5Pj4pOk9ic2VydmFibGU8dm9pZD57XHJcblxyXG4gIHJldHVybiBuZXcgT2JzZXJ2YWJsZTx2b2lkPihzdWJzY3JpYmVyID0+IHtcclxuXHJcbiAgICBpZiAodGhpcy5fcGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldCAmJiB0aGlzLl91dWlkKSB7XHJcbiAgICAgIGxldCB0ciA9IHRoaXMuX3BlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQuaW5kZXhlZERiLnRyYW5zYWN0aW9uKHRoaXMuX3BlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQuc3RvcmVOYW1lLCAncmVhZHdyaXRlJyk7XHJcbiAgICAgIGxldCByZWNGaWxlT2JqU3RvcmUgPSB0ci5vYmplY3RTdG9yZSh0aGlzLl9wZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0LnN0b3JlTmFtZSk7XHJcblxyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGxldCBjaDBEYXRhID0gZGF0YVswXTtcclxuICAgICAgICBsZXQgZGF0YUNoa0NudCA9IGNoMERhdGEubGVuZ3RoO1xyXG4gICAgICAgIGxldCBwb3MgPSAwO1xyXG4gICAgICAgIGZvciAobGV0IGNoQ2tJZHggPSAwOyBjaENrSWR4IDwgZGF0YUNoa0NudDsgY2hDa0lkeCsrKSB7XHJcbiAgICAgICAgICBsZXQgYnVmTGVuID0gMDtcclxuICAgICAgICAgIGZvciAobGV0IGNoID0gMDsgY2ggPCB0aGlzLmNoYW5uZWxDb3VudDsgY2grKykge1xyXG4gICAgICAgICAgICBsZXQgY2hDaGsgPSBkYXRhW2NoXVtjaENrSWR4XTtcclxuICAgICAgICAgICAgYnVmTGVuID0gY2hDaGsubGVuZ3RoO1xyXG4gICAgICAgICAgICAvL2xldCBjYWNoZUlkID0gdXVpZCArICdfJyArIGNoICsgJ18nICsgY2hDa0lkeDtcclxuICAgICAgICAgICAgbGV0IGNoa0RiSWQgPSBbdGhpcy5fdXVpZCwgdGhpcy5pbmREYkNoa0lkeCArIGNoQ2tJZHgsIGNoXTtcclxuICAgICAgICAgICAgbGV0IGNyID0gcmVjRmlsZU9ialN0b3JlLmFkZChjaENoaywgY2hrRGJJZCk7XHJcbiAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIkFkZGVkOiBcIitjaCtcIiBcIisodGhpcy5pbmREYkNoa0lkeCtjaENrSWR4KSk7XHJcbiAgICAgICAgICAgIGNyLm9uc3VjY2VzcyA9ICgpID0+IHtcclxuICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJTdG9yZWQgYXVkaW8gZGF0YSB0byBpbmRleGVkIGRiXCIpO1xyXG4gICAgICAgICAgICAgIC8vIGlmKGNoQ2tJZHg+PSBkYXRhQ2hrQ250LTEgJiYgY2g+PXRoaXMuY2hhbm5lbENvdW50LTEpe1xyXG4gICAgICAgICAgICAgIC8vICAgdHIuY29tbWl0KCk7XHJcbiAgICAgICAgICAgICAgLy8gfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNyLm9uZXJyb3IgPSAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgaWYoIXRoaXMuX3N0b3JlRXJyb3IpIHtcclxuICAgICAgICAgICAgICAgIC8vIE9ubHkgbG9nIHRoZSBmaXJzdCBlcnJvclxyXG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHN0b3JpbmcgYXVkaW8gZGF0YSBvZiBcIiArIGNoQ2hrLmJ5dGVMZW5ndGggKyBcIiBieXRlcyB0byBpbmRleGVkIGRiOiBcIiArIGNyLmVycm9yKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHBvcyArPSBidWZMZW47XHJcbiAgICAgICAgICB0aGlzLl9mcmFtZUxlbis9YnVmTGVuO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmluZERiQ2hrSWR4ICs9IGRhdGFDaGtDbnQ7XHJcblxyXG4gICAgICAgIHRyLm9uZXJyb3IgPSAoZXYpID0+IHtcclxuICAgICAgICAgIGlmKCF0aGlzLl9zdG9yZUVycm9yKSB7XHJcbiAgICAgICAgICAgIC8vIE9ubHkgbG9nIHRoZSBmaXJzdCBlcnJvclxyXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRmFpbGVkIHRvIHN0b3JlIGF1ZGlvIGRhdGEgdG8gaW5kZXhlZCBkYiwgdHJhbnNhY3Rpb24gZXJyb3I6IFwiK3RyLmVycm9yKTtcclxuICAgICAgICAgICAgdGhpcy5fc3RvcmVFcnJvciA9IHRyLmVycm9yO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgc3Vic2NyaWJlci5lcnJvcih0ci5lcnJvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRyLm9uYWJvcnQ9KGV2KT0+e1xyXG4gICAgICAgICAgLy8gSWYgQ2hyb21lIHJlYWNoZXMgcXVvdGEgaXQgYWJvcnRzIHRoZSB0cmFuc2FjdGlvblxyXG4gICAgICAgICAgaWYoIXRoaXMuX3N0b3JlRXJyb3IpIHtcclxuICAgICAgICAgICAgLy8gT25seSBsb2cgdGhlIGZpcnN0IGVycm9yXHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJGYWlsZWQgdG8gc3RvcmUgYXVkaW8gZGF0YSB0byBpbmRleGVkIGRiLCB0cmFuc2FjdGlvbiBhYm9ydGVkOiBcIit0ci5lcnJvcik7XHJcbiAgICAgICAgICAgIHRoaXMuX3N0b3JlRXJyb3IgPSB0ci5lcnJvcjtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHN1YnNjcmliZXIuZXJyb3IodHIuZXJyb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0ci5vbmNvbXBsZXRlID0gKGV2KSA9PiB7XHJcbiAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRyLmNvbW1pdCgpO1xyXG4gICAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgICBzdWJzY3JpYmVyLmVycm9yKG5ldyBFcnJvcignVHJhbnNmZXIgYXVkaW8gZGF0YSBlcnJvcjogJyArIGVycikpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgZnJvbUNodW5rQXVkaW9CdWZmZXIocGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldDpQZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0ICxhdWRpb0J1ZmZlcjpBdWRpb0J1ZmZlcik6T2JzZXJ2YWJsZTxJbmRleGVkRGJBdWRpb0J1ZmZlcj57XHJcblxyXG4gICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlPEluZGV4ZWREYkF1ZGlvQnVmZmVyPihzdWJzY3JpYmVyID0+IHtcclxuICAgICAgbGV0IGNocyA9IGF1ZGlvQnVmZmVyLm51bWJlck9mQ2hhbm5lbHM7XHJcbiAgICAgIGxldCBzciA9IGF1ZGlvQnVmZmVyLnNhbXBsZVJhdGU7XHJcbiAgICAgIGxldCBjaGtGcmFtZUxlbmd0aCA9IGF1ZGlvQnVmZmVyLmxlbmd0aDtcclxuXHJcbiAgICAgIGxldCBpYWIgPSBuZXcgSW5kZXhlZERiQXVkaW9CdWZmZXIocGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldCwgY2hzLCBzciwgY2hrRnJhbWVMZW5ndGgsIDAsIFVVSUQuZ2VuZXJhdGUoKSk7XHJcbiAgICAgIGlhYi5hcHBlbmRDaHVua0F1ZGlvQnVmZmVyKGF1ZGlvQnVmZmVyKS5zdWJzY3JpYmUoXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgbmV4dDogKCk9PntcclxuICAgICAgICAgICAgc3Vic2NyaWJlci5uZXh0KGlhYik7XHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgY29tcGxldGU6ICgpID0+IHtcclxuICAgICAgICAgICAgc3Vic2NyaWJlci5jb21wbGV0ZSgpO1xyXG4gICAgICAgICAgfSxcclxuICAgICAgICAgIGVycm9yOiAoZXJyKT0+e1xyXG4gICAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKGVycik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICApXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGFwcGVuZENodW5rQXVkaW9CdWZmZXIoYXVkaW9CdWZmZXI6QXVkaW9CdWZmZXIpe1xyXG4gICAgaWYodGhpcy5fc2VhbGVkKXtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYXBwZW5kIGF1ZGlvIGJ1ZmZlciB0byBhbHJlYWR5IHNlYWxlZCBhdWRpbyBidWZmZXIuJyk7XHJcbiAgICB9XHJcbiAgICBsZXQgY2hzPWF1ZGlvQnVmZmVyLm51bWJlck9mQ2hhbm5lbHM7XHJcbiAgICBpZih0aGlzLl9jaGFubmVsQ291bnQhPT0gY2hzKXtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYXBwZW5kIGF1ZGlvIGJ1ZmZlciB3aXRoICcrY2hzKycgY2hhbm5lbHMgdG8gdGhpcyBhcnJheSBhdWRpbyBidWZmZXIgd2l0aCAnK3RoaXMuX2NoYW5uZWxDb3VudCsnIGNoYW5uZWxzLiBOdW1iZXIgb2YgY2hhbm5lbHMgbXVzdCBtYXRjaC4nKTtcclxuICAgIH1cclxuICAgIGxldCBzcj1hdWRpb0J1ZmZlci5zYW1wbGVSYXRlO1xyXG4gICAgaWYoc3IhPT10aGlzLl9zYW1wbGVSYXRlKXtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYXBwZW5kIGF1ZGlvIGJ1ZmZlciB3aXRoIHNhbXBsZXJhdGUgJytzcisnIHRvIHRoaXMgYXJyYXkgYXVkaW8gYnVmZmVyIHdpdGggc2FtcGxlcmF0ZSAnK3RoaXMuX3NhbXBsZVJhdGUrJy4gU2FtcGxlcmF0ZXMgbXVzdCBtYXRjaC4nKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgYWJGbD1hdWRpb0J1ZmZlci5sZW5ndGg7XHJcbiAgICBpZihhYkZsPnRoaXMuX2NodW5rRnJhbWVMZW4pe1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhcHBlbmQgYXVkaW8gYnVmZmVyIHdpdGggZnJhbWUgbGVuZ3RoICcrYWJGbCsnIHRvIHRoaXMgYXJyYXkgYXVkaW8gYnVmZmVyIHdpdGggY2h1bmsgZnJhbWUgbGVuZ3RoICcrdGhpcy5fY2h1bmtGcmFtZUxlbisnLiBDaHVuayBsZW5ndGggbXVzdCBiZSBlcXVhbCBvciBsZXNzIGlmIGxhc3QgY2h1bmsuJyk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8dm9pZD4oc3Vic2NyaWJlciA9PiB7XHJcbiAgICAgIGlmICh0aGlzLl9wZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0ICYmIHRoaXMuX3V1aWQpIHtcclxuICAgICAgICBsZXQgdHIgPSB0aGlzLl9wZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0LnRyYW5zYWN0aW9uKCdyZWFkd3JpdGUnKTtcclxuICAgICAgICBsZXQgcmVjRmlsZU9ialN0b3JlID0gdHIub2JqZWN0U3RvcmUodGhpcy5fcGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldC5zdG9yZU5hbWUpO1xyXG4gICAgICAgIHRyeSB7XHJcblxyXG4gICAgICAgICAgICBmb3IgKGxldCBjaCA9IDA7IGNoIDwgdGhpcy5jaGFubmVsQ291bnQ7IGNoKyspIHtcclxuICAgICAgICAgICAgICBsZXQgY2hDaGsgPSBhdWRpb0J1ZmZlci5nZXRDaGFubmVsRGF0YShjaCk7XHJcbiAgICAgICAgICAgICAgbGV0IGNoa0RiSWQgPSBbdGhpcy5fdXVpZCwgdGhpcy5pbmREYkNoa0lkeCsrLCBjaF07XHJcbiAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIGxldCBjciA9IHJlY0ZpbGVPYmpTdG9yZS5hZGQoY2hDaGssIGNoa0RiSWQpO1xyXG4gICAgICAgICAgICAgICAgY3Iub25zdWNjZXNzID0gKGV2KSA9PiB7fVxyXG4gICAgICAgICAgICAgICAgY3Iub25lcnJvciA9IChldikgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAvLyBpUGFkIG1heSB0aHJvdyBRdW90YUV4Y2VlZGVkRXJyb3IgaGVyZVxyXG4gICAgICAgICAgICAgICAgICAvLyBpUGFkIGFza3MgZm9yIG1vcmUgc3RvcmFnZSBhbmQgaWYgZGVuaWVkLCB0aGUgZXJyb3IgaXMgdGhyb3duIGhlcmVcclxuICAgICAgICAgICAgICAgICAgaWYoIXRoaXMuX3N0b3JlRXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBPbmx5IGxvZyB0aGUgZmlyc3QgZXJyb3JcclxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc3RvcmluZyBhdWRpbyBkYXRhIG9mIFwiICsgY2hDaGsuYnl0ZUxlbmd0aCArIFwiIGJ5dGVzIHRvIGluZGV4ZWQgZGI6IFwiICsgY3IuZXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgIC8vc3Vic2NyaWJlci5lcnJvcihjci5lcnJvcik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfWNhdGNoKGVycjE6YW55KXtcclxuICAgICAgICAgICAgICAgIGlmKCF0aGlzLl9zdG9yZUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBhZGRpbmcgYXVkaW8gZGF0YSB0byBpbmRleGVkIGRiIHN0b3JlOiBcIiArIGVycjEpO1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLl9zdG9yZUVycm9yPShlcnIxIGluc3RhbmNlb2YgRXJyb3IpP2VycjE6bmV3IEVycm9yKGVycjEpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5lcnJvcihlcnIxKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5fZnJhbWVMZW4rPWFiRmw7XHJcblxyXG4gICAgICAgICAgdHIub25lcnJvciA9IChldikgPT4ge1xyXG4gICAgICAgICAgICBpZighdGhpcy5fc3RvcmVFcnJvcikge1xyXG4gICAgICAgICAgICAgIC8vIE9ubHkgbG9nIHRoZSBmaXJzdCBlcnJvclxyXG4gICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJGYWlsZWQgdG8gc3RvcmUgYXVkaW8gZGF0YSB0byBpbmRleGVkIGRiLCB0cmFuc2FjdGlvbiBlcnJvcjogXCIrdHIuZXJyb3IpO1xyXG4gICAgICAgICAgICAgIHRoaXMuX3N0b3JlRXJyb3IgPSB0ci5lcnJvcjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKHRyLmVycm9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHRyLm9uYWJvcnQ9KGV2KT0+e1xyXG4gICAgICAgICAgICAvLyBJZiBDaHJvbWUgcmVhY2hlcyBxdW90YSBpdCBhYm9ydHMgdGhlIHRyYW5zYWN0aW9uXHJcbiAgICAgICAgICAgIGlmKCF0aGlzLl9zdG9yZUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgLy8gT25seSBsb2cgdGhlIGZpcnN0IGVycm9yXHJcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkZhaWxlZCB0byBzdG9yZSBhdWRpbyBkYXRhIHRvIGluZGV4ZWQgZGIsIHRyYW5zYWN0aW9uIGFib3J0ZWQ6IFwiK3RyLmVycm9yKTtcclxuICAgICAgICAgICAgICB0aGlzLl9zdG9yZUVycm9yID0gdHIuZXJyb3I7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgc3Vic2NyaWJlci5lcnJvcih0ci5lcnJvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICB0ci5vbmNvbXBsZXRlID0gKGV2KSA9PiB7XHJcbiAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIlRyYW5zYWN0aW9uIGNvbXBsZXRlXCIpO1xyXG4gICAgICAgICAgICBpZihhYkZsPHRoaXMuX2NodW5rRnJhbWVMZW4pe1xyXG4gICAgICAgICAgICAgIC8vIGxhc3QgY2h1bmtcclxuICAgICAgICAgICAgICB0aGlzLnNlYWwoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBzdWJzY3JpYmVyLm5leHQoKTtcclxuICAgICAgICAgICAgc3Vic2NyaWJlci5jb21wbGV0ZSgpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdHIuY29tbWl0KCk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdDYXRjaGVkIGVycm9yOiAnK2Vycik7XHJcbiAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKG5ldyBFcnJvcignVHJhbnNmZXIgYXVkaW8gZGF0YSBlcnJvcjogJyArIGVycikpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICByZWxlYXNlQXVkaW9EYXRhKCk6T2JzZXJ2YWJsZTx2b2lkPntcclxuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZTx2b2lkPigoc3Vic2NyaWJlcik9PntcclxuICAgICAgbGV0IG9zPXRoaXMuX3BlcnNpc3RlbnRBdWRpb1N0b3JhZ2VUYXJnZXQub2JqZWN0U3RvcmUoJ3JlYWR3cml0ZScpO1xyXG4gICAgICB0aGlzLmRlbGV0ZUFsbEJ1ZnMob3MsMCwoKT0+e1xyXG4gICAgICAgIHN1YnNjcmliZXIubmV4dCgpO1xyXG4gICAgICAgIHN1YnNjcmliZXIuY29tcGxldGUoKTtcclxuICAgICAgfSwoZXJyKT0+e1xyXG4gICAgICAgIHN1YnNjcmliZXIuZXJyb3IoZXJyKTtcclxuICAgICAgfSlcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgdG9TdHJpbmcoKTpzdHJpbmd7XHJcbiAgICByZXR1cm4gXCJJbmRleGVkIGRiIGF1ZGlvIGJ1ZmZlci4gQ2hhbm5lbHM6IFwiK3RoaXMuY2hhbm5lbENvdW50K1wiLCBzYW1wbGUgcmF0ZTogXCIrdGhpcy5zYW1wbGVSYXRlK1wiLCBjaHVuayBmcmFtZSBsZW5ndGg6IFwiK3RoaXMuX2NodW5rRnJhbWVMZW4rXCIsIG51bWJlciBvZiBjaHVua3M6IFwiK3RoaXMuY2h1bmtDb3VudCtcIiwgZnJhbWUgbGVuZ3RoOiBcIit0aGlzLmZyYW1lTGVuK1wiLCBzZWFsZWQ6IFwiK3RoaXMuc2VhbGVkKCk7XHJcbiAgfVxyXG5cclxuICBhc3luY0F1ZGlvSW5wdXRTdHJlYW0oKTogQXN5bmNGbG9hdDMyQXJyYXlJbnB1dFN0cmVhbSB8IG51bGwge1xyXG4gICAgcmV0dXJuIG5ldyBJbmRleGVkRGJBdWRpb0lucHV0U3RyZWFtKHRoaXMpO1xyXG4gIH1cclxuXHJcbiAgYXVkaW9JbnB1dFN0cmVhbSgpOiBGbG9hdDMyQXJyYXlJbnB1dFN0cmVhbSB8IG51bGwge1xyXG4gICAgLy8gU3luY2hyb25vdXMgc3RyZWFtIG5vdCBzdXBwb3J0ZWRcclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgZ2V0IGR1cmF0aW9uKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gdGhpcy5fY2h1bmtGcmFtZUxlbi90aGlzLl9zYW1wbGVSYXRlO1xyXG4gIH1cclxuXHJcbiAgZ2V0IG51bWJlck9mQ2hhbm5lbHMoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLl9jaGFubmVsQ291bnQ7XHJcbiAgfVxyXG5cclxuICBzYW1wbGVDb3VudHMoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLl9jaGFubmVsQ291bnQqdGhpcy5fZnJhbWVMZW47XHJcbiAgfVxyXG5cclxuICByYW5kb21BY2Nlc3NBdWRpb1N0cmVhbSgpOiBSYW5kb21BY2Nlc3NBdWRpb1N0cmVhbSB7XHJcbiAgICByZXR1cm4gbmV3IEluZGV4ZWREYlJhbmRvbUFjY2Vzc1N0cmVhbSh0aGlzKTtcclxuICB9XHJcblxyXG59XHJcblxyXG5cclxuZXhwb3J0IGNsYXNzIEluZGV4ZWREYlJhbmRvbUFjY2Vzc1N0cmVhbSBpbXBsZW1lbnRzIFJhbmRvbUFjY2Vzc0F1ZGlvU3RyZWFte1xyXG5cclxuICBwcml2YXRlIF9jdXJyQ2k9MDtcclxuICBwcml2YXRlIF9jY0NhY2hlOkZsb2F0MzJBcnJheVtdfG51bGw9bnVsbDtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfaW5kZGJBYjpJbmRleGVkRGJBdWRpb0J1ZmZlcikge1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjaHVuayhvczpJREJPYmplY3RTdG9yZSxjaTpudW1iZXIsY2I6KGJ1ZnM6QXJyYXk8RmxvYXQzMkFycmF5PnxudWxsKT0+dm9pZCxlcnJDYjooZXJyOkVycm9yKT0+dm9pZCl7XHJcblxyXG4gICAgLy8gQnVpbGQgYm91bmRzIGZvciBjaGFubmVsc1xyXG4gICAgbGV0IGxJZHg9W3RoaXMuX2luZGRiQWIudXVpZCxjaSwwXTtcclxuICAgIGxldCBoSWR4PVt0aGlzLl9pbmRkYkFiLnV1aWQsY2ksdGhpcy5faW5kZGJBYi5jaGFubmVsQ291bnRdO1xyXG4gICAgbGV0IGNoc0tyPUlEQktleVJhbmdlLmJvdW5kKGxJZHgsaElkeCk7XHJcblxyXG4gICAgbGV0IHJxPW9zLmdldEFsbChjaHNLcik7XHJcblxyXG4gICAgcnEub25zdWNjZXNzPSgpPT57XHJcbiAgICAgIGxldCBjYz1ycS5yZXN1bHQ7XHJcbiAgICAgIGxldCBjYzA7XHJcbiAgICAgIGxldCBjY0Nocz1jYy5sZW5ndGg7XHJcbiAgICAgIGlmKGNjQ2hzPT0wKXtcclxuICAgICAgICBjYihudWxsKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgaWYoY2NDaHMhPT10aGlzLl9pbmRkYkFiLmNoYW5uZWxDb3VudCl7XHJcbiAgICAgICAgZXJyQ2IobmV3IEVycm9yKCdOdW1iZXIgb2YgY2hhbm5lbHMgb2YgaW5kZGIgZGF0YSAoJytjY0NocysnKSBkb2VzIG5vdCBtYXRjaCBudW1iZXIgb2YgY2hhbm5lbHMgKCcrdGhpcy5faW5kZGJBYi5jaGFubmVsQ291bnQrJyknKSk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgIH1cclxuICAgICAgaWYoY2MubGVuZ3RoPjApe1xyXG4gICAgICAgIGNjMD1jY1swXTtcclxuICAgICAgfVxyXG4gICAgICBsZXQgYXJyQnVmPW5ldyBBcnJheTxGbG9hdDMyQXJyYXk+KCk7XHJcbiAgICAgIGxldCBjY0xlbj1jYzAubGVuZ3RoO1xyXG4gICAgICBmb3IobGV0IGNoPTA7Y2g8Y2NDaHM7Y2grKyl7XHJcbiAgICAgICAgbGV0IGNoQXJyPW5ldyBGbG9hdDMyQXJyYXkoY2NMZW4pO1xyXG4gICAgICAgIGZvcihsZXQgc2k9MDtzaTxjY0xlbjtzaSsrKXtcclxuICAgICAgICAgIGNoQXJyW3NpXT1jY1tjaF1bc2ldO1xyXG4gICAgICAgIH1cclxuICAgICAgICBhcnJCdWYucHVzaChjaEFycik7XHJcbiAgICAgIH1cclxuICAgICAgY2IoYXJyQnVmKTtcclxuICAgIH1cclxuICAgIHJxLm9uZXJyb3I9KGVyckV2KT0+e1xyXG4gICAgICBlcnJDYihuZXcgRXJyb3IoZXJyRXYudG9TdHJpbmcoKSkpO1xyXG4gICAgfVxyXG5cclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2ZpbGxCdWZzKGNjQnVmczpGbG9hdDMyQXJyYXlbXSx0cmdTdGF0ZTp7ZnJhbWVQb3M6bnVtYmVyLGZyYW1lTGVuOm51bWJlcix0cmdCdWZzOkZsb2F0MzJBcnJheVtdLGZpbGxlZDpudW1iZXJ9LHNyY1N0YXRlOntzcmNGcmFtZVBvczpudW1iZXIsY2k6bnVtYmVyLGNjUG9zOm51bWJlcn0pe1xyXG4gICAgbGV0IGNjQnVmc0Nocz1jY0J1ZnMubGVuZ3RoO1xyXG4gICAgaWYoY2NCdWZzQ2hzPjApIHtcclxuICAgICAgbGV0IGNjQnVmMCA9IGNjQnVmc1swXTtcclxuICAgICAgbGV0IGNjQnVmc0xlbiA9IGNjQnVmMC5sZW5ndGg7XHJcblxyXG4gICAgICAvL2NvbnNvbGUuZGVidWcoJ0luZGV4ZWREYkF1ZGlvQnVmZmVyOjpmaWxsQnVmcyBmcmFtZVBvczogJytmcmFtZVBvcysnLCBzcmNGcmFtZVBvczogJytzcmNGcmFtZVBvcysnLCBjY0J1ZnNMZW46ICcrY2NCdWZzTGVuKTtcclxuICAgICAgaWYgKHRyZ1N0YXRlLmZyYW1lUG9zID49IHNyY1N0YXRlLnNyY0ZyYW1lUG9zICsgY2NCdWZzTGVuKSB7XHJcbiAgICAgICAgLy8gdGFyZ2V0IGZyYW1lIHBvc2l0aW9uIGlzIGFoZWFkLCBzZWVrIHRvIG5leHQgc291cmNlIGJ1ZmZlclxyXG4gICAgICAgIC8vY29uc29sZS5kZWJ1ZygnSW5kZXhlZERiQXVkaW9CdWZmZXI6OmZpbGxCdWZzIHNlZWsgdG8gbmV4dCBpbmRkYiBidWZmZXInKTtcclxuICAgICAgICB0aGlzLl9jY0NhY2hlPW51bGw7XHJcbiAgICAgICAgc3JjU3RhdGUuY2krKztcclxuICAgICAgICBzcmNTdGF0ZS5jY1Bvcz0wO1xyXG4gICAgICAgIHNyY1N0YXRlLnNyY0ZyYW1lUG9zKz1jY0J1ZnNMZW47XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gQXNzdW1pbmcgdGFyZ2V0IGZyYW1lIHBvcyBpcyBpbnNpZGUgY3VycmVudCBzb3VyY2UgYnVmZmVyXHJcbiAgICAgICAgc3JjU3RhdGUuY2NQb3M9dHJnU3RhdGUuZnJhbWVQb3Mtc3JjU3RhdGUuc3JjRnJhbWVQb3M7XHJcbiAgICAgICAgbGV0IGNjQXZhaWwgPSBjY0J1ZnNMZW4gLSBzcmNTdGF0ZS5jY1BvcztcclxuICAgICAgICBsZXQgdG9Db3B5ID0gY2NCdWZzTGVuO1xyXG5cclxuICAgICAgICBpZiAodG9Db3B5ID4gY2NBdmFpbCkge1xyXG4gICAgICAgICAgdG9Db3B5ID0gY2NBdmFpbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHRvQ29weSA+IHRyZ1N0YXRlLmZyYW1lTGVuKSB7XHJcbiAgICAgICAgICB0b0NvcHkgPSB0cmdTdGF0ZS5mcmFtZUxlbjtcclxuICAgICAgICB9XHJcbiAgICAgICAgZm9yIChsZXQgY2ggPSAwOyBjaCA8IGNjQnVmc0NoczsgY2grKykge1xyXG4gICAgICAgICAgZm9yIChsZXQgc2kgPSAwOyBzaSA8IHRvQ29weTsgc2krKykge1xyXG4gICAgICAgICAgICB0cmdTdGF0ZS50cmdCdWZzW2NoXVt0cmdTdGF0ZS5maWxsZWQrc2ldID0gY2NCdWZzW2NoXVtzcmNTdGF0ZS5jY1BvcytzaV07XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRyZ1N0YXRlLmZpbGxlZCArPSB0b0NvcHk7XHJcbiAgICAgICAgdHJnU3RhdGUuZnJhbWVMZW4gLT0gdG9Db3B5O1xyXG4gICAgICAgIHRyZ1N0YXRlLmZyYW1lUG9zICs9IHRvQ29weTtcclxuICAgICAgICBzcmNTdGF0ZS5jY1BvcyArPSB0b0NvcHk7XHJcbiAgICAgICAgaWYgKHNyY1N0YXRlLmNjUG9zID49IGNjQnVmc0xlbikge1xyXG4gICAgICAgICAgLy8gSW52YWxpZGF0ZSBjYWNoZVxyXG4gICAgICAgICAgdGhpcy5fY2NDYWNoZT1udWxsO1xyXG4gICAgICAgICAgc3JjU3RhdGUuY2krKztcclxuICAgICAgICAgIHRoaXMuX2N1cnJDaT1zcmNTdGF0ZS5jaTtcclxuICAgICAgICAgIHNyY1N0YXRlLmNjUG9zID0gMDtcclxuICAgICAgICAgIHNyY1N0YXRlLnNyY0ZyYW1lUG9zKz1jY0J1ZnNMZW47XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBmaWxsQnVmcyhvczpJREJPYmplY3RTdG9yZSx0cmdTdGF0ZTp7ZnJhbWVQb3M6bnVtYmVyLGZyYW1lTGVuOm51bWJlcix0cmdCdWZzOkZsb2F0MzJBcnJheVtdLGZpbGxlZDpudW1iZXJ9LHNyY1N0YXRlOntzcmNGcmFtZVBvczpudW1iZXIsY2k6bnVtYmVyLGNjUG9zOm51bWJlcixjY0ZpbGxlZDpudW1iZXJ9LGNiOihmaWxsZWQ6bnVtYmVyKT0+dm9pZCxjYkVuZDooZmlsbGVkOm51bWJlcik9PnZvaWQsY2JFcnI6KGVycjpFcnJvcik9PnZvaWQpe1xyXG4gICAgLy9jb25zb2xlLmRlYnVnKCdJbmRleGVkRGJBdWRpb0J1ZmZlcjo6ZmlsbEJ1ZnM6IGZyYW1lUG9zOicrdHJnU3RhdGUuZnJhbWVQb3MrJywgZnJhbWVMZW46ICcrdHJnU3RhdGUuZnJhbWVMZW4rJywgZmlsbGVkOiAnK3RyZ1N0YXRlLmZpbGxlZCsnLCBzcmNGcmFtZVBvczogJytzcmNTdGF0ZS5zcmNGcmFtZVBvcysnLGNpOiAnK3NyY1N0YXRlLmNpKycsIGNjUG9zOiAnK3NyY1N0YXRlLmNjUG9zKTtcclxuICAgIGlmKHRoaXMuX2NjQ2FjaGUpe1xyXG4gICAgICB0aGlzLl9maWxsQnVmcyh0aGlzLl9jY0NhY2hlLHRyZ1N0YXRlLHNyY1N0YXRlKTtcclxuICAgICAgLy9jb25zb2xlLmRlYnVnKCdJbmRleGVkRGJBdWRpb0J1ZmZlcjo6ZmlsbEJ1ZnMgZnJhbWVMZW46ICcrdHJnU3RhdGUuZnJhbWVMZW4pO1xyXG4gICAgICBpZih0cmdTdGF0ZS5mcmFtZUxlbj09PTApe1xyXG4gICAgICAgIC8vY29uc29sZS5kZWJ1ZygnSW5kZXhlZERiQXVkaW9CdWZmZXI6OmZpbGxCdWZzIChmcmFtZWxlbj09MCkgY2FsbDogY2JlbmQgJyt0cmdTdGF0ZS5maWxsZWQpO1xyXG4gICAgICAgIGNiRW5kKHRyZ1N0YXRlLmZpbGxlZCk7XHJcbiAgICAgIH1lbHNlIHtcclxuICAgICAgICB0aGlzLmZpbGxCdWZzKG9zLCB0cmdTdGF0ZSwgc3JjU3RhdGUsIGNiLCBjYkVuZCwgY2JFcnIpO1xyXG4gICAgICB9XHJcbiAgICB9ZWxzZSB7XHJcbiAgICAgIHRoaXMuY2h1bmsob3MsIHNyY1N0YXRlLmNpLCAoY2NCdWZzKSA9PiB7XHJcbiAgICAgICAgaWYgKGNjQnVmcykge1xyXG4gICAgICAgICAgdGhpcy5fY3VyckNpID0gc3JjU3RhdGUuY2k7XHJcbiAgICAgICAgICB0aGlzLl9jY0NhY2hlID0gY2NCdWZzO1xyXG5cclxuICAgICAgICAgIHRoaXMuX2ZpbGxCdWZzKGNjQnVmcywgdHJnU3RhdGUsIHNyY1N0YXRlKTtcclxuICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZygnSW5kZXhlZERiQXVkaW9CdWZmZXI6OmZpbGxCdWZzIGZyYW1lTGVuOiAnK3RyZ1N0YXRlLmZyYW1lTGVuKTtcclxuICAgICAgICAgIGlmICh0cmdTdGF0ZS5mcmFtZUxlbiA9PT0gMCkge1xyXG4gICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoJ0luZGV4ZWREYkF1ZGlvQnVmZmVyOjpmaWxsQnVmcyAoZnJhbWVsZW49PTApIGNhbGw6IGNiZW5kICcrdHJnU3RhdGUuZmlsbGVkKTtcclxuICAgICAgICAgICAgY2JFbmQodHJnU3RhdGUuZmlsbGVkKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuZmlsbEJ1ZnMob3MsdHJnU3RhdGUsIHNyY1N0YXRlLCBjYiwgY2JFbmQsIGNiRXJyKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgLy9jb25zb2xlLmRlYnVnKCdJbmRleGVkRGJBdWRpb0J1ZmZlcjo6ZmlsbEJ1ZnMgKGNodW5rIG5vdCBmb3VuZCkgY2FsbDogY2JlbmQgJyt0cmdTdGF0ZS5maWxsZWQpO1xyXG4gICAgICAgICAgY2JFbmQodHJnU3RhdGUuZmlsbGVkKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0sIChlcnIpID0+IHtcclxuICAgICAgICBjYkVycihlcnIpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG5cclxuICBmcmFtZXNPYnMoZnJhbWVQb3M6bnVtYmVyLGZyYW1lTGVuOm51bWJlcixidWZzOkZsb2F0MzJBcnJheVtdKTpPYnNlcnZhYmxlPG51bWJlcj57XHJcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8bnVtYmVyPigoc3Vic2NyaWJlcik9PntcclxuICAgICAgbGV0IHRyPXRoaXMuX2luZGRiQWIucGVyc2lzdGVudEF1ZGlvU3RvcmFnZVRhcmdldC50cmFuc2FjdGlvbigpO1xyXG4gICAgICBsZXQgb3M9dHIub2JqZWN0U3RvcmUodGhpcy5faW5kZGJBYi5wZXJzaXN0ZW50QXVkaW9TdG9yYWdlVGFyZ2V0LnN0b3JlTmFtZSk7XHJcbiAgICAgIC8vIFBvc2l0aW9uaW5nXHJcbiAgICAgIGxldCBuZXdDaT1NYXRoLmZsb29yKGZyYW1lUG9zL3RoaXMuX2luZGRiQWIuY2h1bmtGcmFtZUxlbik7XHJcbiAgICAgIGlmKG5ld0NpIT09dGhpcy5fY3VyckNpKXtcclxuICAgICAgICB0aGlzLl9jdXJyQ2k9bmV3Q2k7XHJcbiAgICAgICAgdGhpcy5fY2NDYWNoZT1udWxsO1xyXG4gICAgICB9XHJcbiAgICAgIGxldCBzcmNGcmFtZVBvcz1uZXdDaSp0aGlzLl9pbmRkYkFiLmNodW5rRnJhbWVMZW47XHJcbiAgICAgIGxldCB0cmdTdGF0ZT17ZnJhbWVQb3M6ZnJhbWVQb3MsZnJhbWVMZW46ZnJhbWVMZW4sdHJnQnVmczpidWZzLGZpbGxlZDowfTtcclxuICAgICAgbGV0IHNyY1N0YXRlPXtzcmNGcmFtZVBvczpzcmNGcmFtZVBvcyxjaTpuZXdDaSxjY1BvczowLGNjRmlsbGVkOjB9O1xyXG4gICAgICB0aGlzLmZpbGxCdWZzKG9zLHRyZ1N0YXRlLHNyY1N0YXRlLCh2YWwpPT57fSwoZmlsbGVkOm51bWJlcik9PntcclxuICAgICAgICBzdWJzY3JpYmVyLm5leHQoZmlsbGVkKTtcclxuICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XHJcbiAgICAgIH0sZXJyID0+IHtcclxuICAgICAgICBzdWJzY3JpYmVyLmVycm9yKGVycik7XHJcbiAgICAgIH0pXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGNsb3NlKCk6IHZvaWQge1xyXG4gICAgdGhpcy5fY3VyckNpPTA7XHJcbiAgICB0aGlzLl9jY0NhY2hlPW51bGw7XHJcbiAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgSW5kZXhlZERiQXVkaW9JbnB1dFN0cmVhbSBpbXBsZW1lbnRzIEFzeW5jRmxvYXQzMkFycmF5SW5wdXRTdHJlYW17XHJcblxyXG4gIHByaXZhdGUgZnJhbWVQb3M6bnVtYmVyPTA7XHJcbiAgcHJpdmF0ZSBpbmRkYkFiU3RyOkluZGV4ZWREYlJhbmRvbUFjY2Vzc1N0cmVhbTtcclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGluZGRiQWI6SW5kZXhlZERiQXVkaW9CdWZmZXIpIHtcclxuICAgICAgdGhpcy5pbmRkYkFiU3RyPW5ldyBJbmRleGVkRGJSYW5kb21BY2Nlc3NTdHJlYW0oaW5kZGJBYik7XHJcbiAgfVxyXG5cclxuICBjbG9zZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuaW5kZGJBYlN0ci5jbG9zZSgpO1xyXG4gIH1cclxuXHJcbiAgcmVhZE9icyhidWZmZXJzOiBBcnJheTxGbG9hdDMyQXJyYXk+KTogT2JzZXJ2YWJsZTxudW1iZXI+IHtcclxuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZTxudW1iZXI+KHN1YnNjcj0+IHtcclxuICAgICAgaWYgKGJ1ZmZlcnMgJiYgYnVmZmVycy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgbGV0IGZsID0gYnVmZmVyc1swXS5sZW5ndGg7XHJcbiAgICAgICAgdGhpcy5pbmRkYkFiU3RyLmZyYW1lc09icyh0aGlzLmZyYW1lUG9zLCBmbCwgYnVmZmVycykuc3Vic2NyaWJlKHtcclxuICAgICAgICAgIG5leHQ6IChyZWFkKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuZnJhbWVQb3MgKz0gcmVhZDtcclxuICAgICAgICAgICAgc3Vic2NyLm5leHQocmVhZCk7XHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgY29tcGxldGU6ICgpID0+IHtcclxuICAgICAgICAgICAgc3Vic2NyLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgZXJyb3I6IChlcnIpID0+IHtcclxuICAgICAgICAgICAgc3Vic2NyLmVycm9yKGVycik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSlcclxuICAgICAgfWVsc2V7XHJcbiAgICAgICAgc3Vic2NyLm5leHQoMCk7XHJcbiAgICAgICAgc3Vic2NyLmNvbXBsZXRlKCk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc2tpcEZyYW1lcyhuOiBudW1iZXIpOnZvaWQge1xyXG4gICAgdGhpcy5mcmFtZVBvcys9bjtcclxuICB9XHJcblxyXG59XHJcbiJdfQ==