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.
- package/esm2022/lib/action/action.mjs +73 -0
- package/{esm2020 → esm2022}/lib/audio/array_audio_buffer.mjs +163 -163
- package/{esm2020 → esm2022}/lib/audio/array_audio_buffer_input_stream.mjs +85 -85
- package/{esm2020 → esm2022}/lib/audio/array_audio_buffer_random_access_stream.mjs +15 -15
- package/esm2022/lib/audio/audio_data_holder.mjs +264 -0
- package/{esm2020 → esm2022}/lib/audio/audio_display.mjs +93 -93
- package/{esm2020 → esm2022}/lib/audio/audio_player.mjs +213 -213
- package/esm2022/lib/audio/capture/capture.mjs +855 -0
- package/esm2022/lib/audio/context.mjs +79 -0
- package/{esm2020 → esm2022}/lib/audio/dsp/level_measure.mjs +515 -515
- package/{esm2020 → esm2022}/lib/audio/format.mjs +16 -16
- package/esm2022/lib/audio/impl/wavformat.mjs +6 -0
- package/{esm2020 → esm2022}/lib/audio/impl/wavreader.mjs +133 -133
- package/esm2022/lib/audio/impl/wavwriter.mjs +105 -0
- package/esm2022/lib/audio/inddb_audio_buffer.mjs +508 -0
- package/{esm2020 → esm2022}/lib/audio/io/stream.mjs +58 -58
- package/esm2022/lib/audio/net_audio_buffer.mjs +293 -0
- package/{esm2020 → esm2022}/lib/audio/persistor.mjs +80 -80
- package/{esm2020 → esm2022}/lib/audio/playback/array_audio_buffer_source_node.mjs +125 -125
- package/esm2022/lib/audio/playback/audio_source_node.mjs +18 -0
- package/esm2022/lib/audio/playback/audio_source_worklet_module_loader.mjs +167 -0
- package/{esm2020 → esm2022}/lib/audio/playback/inddb_audio_buffer_source_node.mjs +166 -166
- package/{esm2020 → esm2022}/lib/audio/playback/net_audio_buffer_source_node.mjs +217 -217
- package/esm2022/lib/audio/playback/player.mjs +402 -0
- package/esm2022/lib/audio/ui/audio_canvas_layer_comp.mjs +347 -0
- package/{esm2020 → esm2022}/lib/audio/ui/audio_display_control.mjs +65 -65
- package/{esm2020 → esm2022}/lib/audio/ui/audio_display_scroll_pane.mjs +139 -139
- package/{esm2020 → esm2022}/lib/audio/ui/audiosignal.mjs +524 -524
- package/{esm2020 → esm2022}/lib/audio/ui/common.mjs +18 -18
- package/esm2022/lib/audio/ui/container.mjs +414 -0
- package/{esm2020 → esm2022}/lib/audio/ui/livelevel.mjs +352 -352
- package/esm2022/lib/audio/ui/scroll_pane_horizontal.mjs +11 -0
- package/esm2022/lib/audio/ui/sonagram.mjs +900 -0
- package/esm2022/lib/db/inddb.mjs +120 -0
- package/esm2022/lib/dsp/utils.mjs +48 -0
- package/{esm2020 → esm2022}/lib/io/BinaryReader.mjs +84 -84
- package/esm2022/lib/io/BinaryWriter.mjs +74 -0
- package/{esm2020 → esm2022}/lib/io/stream.mjs +258 -258
- package/{esm2020 → esm2022}/lib/math/2d/geometry.mjs +27 -27
- package/esm2022/lib/math/complex.mjs +58 -0
- package/{esm2020 → esm2022}/lib/math/dft.mjs +195 -195
- package/{esm2020 → esm2022}/lib/media/utils.mjs +13 -13
- package/esm2022/lib/net/uploader.mjs +367 -0
- package/{esm2020 → esm2022}/lib/recorder_component.mjs +64 -64
- package/esm2022/lib/speechrecorder/project/project.mjs +49 -0
- package/esm2022/lib/speechrecorder/project/project.service.mjs +64 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/recording.mjs +123 -123
- package/esm2022/lib/speechrecorder/recordings/basic_recording.service.mjs +218 -0
- package/esm2022/lib/speechrecorder/recordings/recordings.service.mjs +1014 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/script/script.mjs +114 -114
- package/{esm2020 → esm2022}/lib/speechrecorder/script/script.service.mjs +47 -47
- package/esm2022/lib/speechrecorder/session/audiorecorder.mjs +1179 -0
- package/esm2022/lib/speechrecorder/session/basicrecorder.mjs +668 -0
- package/esm2022/lib/speechrecorder/session/controlpanel.mjs +416 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/item.mjs +29 -29
- package/{esm2020 → esm2022}/lib/speechrecorder/session/progress.mjs +69 -69
- package/{esm2020 → esm2022}/lib/speechrecorder/session/prompting.mjs +571 -571
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recorder_combi_pane.mjs +65 -65
- package/esm2022/lib/speechrecorder/session/recording_file_cache.mjs +195 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recording_list.mjs +103 -103
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-meta.component.mjs +63 -63
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-navi.component.mjs +51 -51
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.mjs +104 -104
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file-view.component.mjs +381 -381
- package/{esm2020 → esm2022}/lib/speechrecorder/session/recordingfile/recording-file.mjs +67 -67
- package/esm2022/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +288 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/session.mjs +1 -1
- package/esm2022/lib/speechrecorder/session/session.service.mjs +69 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/session_finished_dialog.mjs +29 -29
- package/esm2022/lib/speechrecorder/session/sessionmanager.mjs +1386 -0
- package/{esm2020 → esm2022}/lib/speechrecorder/session/warning_bar.mjs +28 -28
- package/{esm2020 → esm2022}/lib/speechrecorder/spruploader.mjs +22 -22
- package/{esm2020 → esm2022}/lib/speechrecorder/startstopsignal/startstopsignal.mjs +1 -1
- package/esm2022/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.mjs +57 -0
- package/{esm2020 → esm2022}/lib/speechrecorderng.component.mjs +388 -388
- package/{esm2020 → esm2022}/lib/speechrecorderng.module.mjs +100 -100
- package/{esm2020 → esm2022}/lib/spr.config.mjs +26 -26
- package/{esm2020 → esm2022}/lib/spr.module.version.mjs +2 -2
- package/{esm2020 → esm2022}/lib/ui/canvas_layer_comp.mjs +38 -38
- package/{esm2020 → esm2022}/lib/ui/message_dialog.mjs +30 -30
- package/esm2022/lib/ui/recordingitem_display.mjs +253 -0
- package/{esm2020 → esm2022}/lib/ui/responsive_component.mjs +24 -24
- package/{esm2020 → esm2022}/lib/utils/scrollIntoViewToBottom.mjs +23 -23
- package/esm2022/lib/utils/ua-parser.mjs +190 -0
- package/esm2022/lib/utils/utils.mjs +105 -0
- package/esm2022/lib/utils/wake_lock.mjs +114 -0
- package/{esm2020 → esm2022}/lib/utils/wake_lock_media.mjs +1 -1
- package/{esm2020 → esm2022}/public-api.mjs +33 -33
- package/{esm2020 → esm2022}/speechrecorderng.mjs +4 -4
- package/{fesm2020 → fesm2022}/speechrecorderng.mjs +16518 -16454
- package/fesm2022/speechrecorderng.mjs.map +1 -0
- package/index.d.ts +5 -5
- package/lib/action/action.d.ts +27 -27
- package/lib/audio/array_audio_buffer.d.ts +31 -31
- package/lib/audio/array_audio_buffer_input_stream.d.ts +14 -14
- package/lib/audio/array_audio_buffer_random_access_stream.d.ts +9 -9
- package/lib/audio/audio_data_holder.d.ts +84 -84
- package/lib/audio/audio_display.d.ts +36 -36
- package/lib/audio/audio_player.d.ts +47 -47
- package/lib/audio/capture/capture.d.ts +67 -67
- package/lib/audio/context.d.ts +6 -6
- package/lib/audio/dsp/level_measure.d.ts +60 -60
- package/lib/audio/format.d.ts +11 -11
- package/lib/audio/impl/wavformat.d.ts +5 -5
- package/lib/audio/impl/wavreader.d.ts +16 -16
- package/lib/audio/impl/wavwriter.d.ts +13 -13
- package/lib/audio/inddb_audio_buffer.d.ts +68 -68
- package/lib/audio/io/stream.d.ts +28 -28
- package/lib/audio/net_audio_buffer.d.ts +57 -57
- package/lib/audio/persistor.d.ts +29 -29
- package/lib/audio/playback/array_audio_buffer_source_node.d.ts +18 -18
- package/lib/audio/playback/audio_source_node.d.ts +10 -10
- package/lib/audio/playback/audio_source_worklet_module_loader.d.ts +4 -4
- package/lib/audio/playback/inddb_audio_buffer_source_node.d.ts +21 -21
- package/lib/audio/playback/net_audio_buffer_source_node.d.ts +27 -27
- package/lib/audio/playback/player.d.ts +65 -65
- package/lib/audio/ui/audio_canvas_layer_comp.d.ts +68 -68
- package/lib/audio/ui/audio_display_control.d.ts +25 -25
- package/lib/audio/ui/audio_display_scroll_pane.d.ts +26 -26
- package/lib/audio/ui/audiosignal.d.ts +30 -30
- package/lib/audio/ui/common.d.ts +11 -11
- package/lib/audio/ui/container.d.ts +63 -63
- package/lib/audio/ui/livelevel.d.ts +60 -60
- package/lib/audio/ui/scroll_pane_horizontal.d.ts +5 -5
- package/lib/audio/ui/sonagram.d.ts +37 -37
- package/lib/db/inddb.d.ts +21 -21
- package/lib/dsp/utils.d.ts +19 -19
- package/lib/io/BinaryReader.d.ts +18 -18
- package/lib/io/BinaryWriter.d.ts +15 -15
- package/lib/io/stream.d.ts +59 -59
- package/lib/math/2d/geometry.d.ts +18 -18
- package/lib/math/complex.d.ts +17 -17
- package/lib/math/dft.d.ts +22 -22
- package/lib/media/utils.d.ts +3 -3
- package/lib/net/uploader.d.ts +81 -81
- package/lib/recorder_component.d.ts +16 -16
- package/lib/speechrecorder/project/project.d.ts +59 -59
- package/lib/speechrecorder/project/project.service.d.ts +21 -21
- package/lib/speechrecorder/recording.d.ts +51 -51
- package/lib/speechrecorder/recordings/basic_recording.service.d.ts +27 -27
- package/lib/speechrecorder/recordings/recordings.service.d.ts +48 -48
- package/lib/speechrecorder/script/script.d.ts +80 -79
- package/lib/speechrecorder/script/script.service.d.ts +16 -16
- package/lib/speechrecorder/session/audiorecorder.d.ts +122 -122
- package/lib/speechrecorder/session/basicrecorder.d.ts +139 -139
- package/lib/speechrecorder/session/controlpanel.d.ts +109 -107
- package/lib/speechrecorder/session/item.d.ts +12 -12
- package/lib/speechrecorder/session/progress.d.ts +17 -17
- package/lib/speechrecorder/session/prompting.d.ts +121 -121
- package/lib/speechrecorder/session/recorder_combi_pane.d.ts +32 -32
- package/lib/speechrecorder/session/recording_file_cache.d.ts +33 -33
- package/lib/speechrecorder/session/recording_list.d.ts +24 -24
- package/lib/speechrecorder/session/recordingfile/recording-file-meta.component.d.ts +15 -15
- package/lib/speechrecorder/session/recordingfile/recording-file-navi.component.d.ts +20 -20
- package/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.d.ts +31 -31
- package/lib/speechrecorder/session/recordingfile/recording-file-view.component.d.ts +55 -55
- package/lib/speechrecorder/session/recordingfile/recording-file.d.ts +7 -7
- package/lib/speechrecorder/session/recordingfile/recordingfile-service.d.ts +24 -24
- package/lib/speechrecorder/session/session.d.ts +15 -15
- package/lib/speechrecorder/session/session.service.d.ts +20 -20
- package/lib/speechrecorder/session/session_finished_dialog.d.ts +10 -10
- package/lib/speechrecorder/session/sessionmanager.d.ts +129 -123
- package/lib/speechrecorder/session/warning_bar.d.ts +8 -8
- package/lib/speechrecorder/spruploader.d.ts +11 -11
- package/lib/speechrecorder/startstopsignal/startstopsignal.d.ts +10 -10
- package/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.d.ts +11 -11
- package/lib/speechrecorderng.component.d.ts +61 -61
- package/lib/speechrecorderng.module.d.ts +56 -56
- package/lib/spr.config.d.ts +17 -17
- package/lib/spr.module.version.d.ts +1 -1
- package/lib/ui/canvas_layer_comp.d.ts +13 -13
- package/lib/ui/message_dialog.d.ts +10 -10
- package/lib/ui/recordingitem_display.d.ts +84 -84
- package/lib/ui/responsive_component.d.ts +9 -9
- package/lib/utils/scrollIntoViewToBottom.d.ts +9 -9
- package/lib/utils/ua-parser.d.ts +43 -43
- package/lib/utils/utils.d.ts +19 -19
- package/lib/utils/wake_lock.d.ts +23 -23
- package/lib/utils/wake_lock_media.d.ts +1 -1
- package/package.json +17 -23
- package/public-api.d.ts +33 -33
- package/esm2020/lib/action/action.mjs +0 -73
- package/esm2020/lib/audio/audio_data_holder.mjs +0 -264
- package/esm2020/lib/audio/capture/capture.mjs +0 -855
- package/esm2020/lib/audio/context.mjs +0 -79
- package/esm2020/lib/audio/impl/wavformat.mjs +0 -6
- package/esm2020/lib/audio/impl/wavwriter.mjs +0 -105
- package/esm2020/lib/audio/inddb_audio_buffer.mjs +0 -508
- package/esm2020/lib/audio/net_audio_buffer.mjs +0 -293
- package/esm2020/lib/audio/playback/audio_source_node.mjs +0 -18
- package/esm2020/lib/audio/playback/audio_source_worklet_module_loader.mjs +0 -167
- package/esm2020/lib/audio/playback/player.mjs +0 -402
- package/esm2020/lib/audio/ui/audio_canvas_layer_comp.mjs +0 -347
- package/esm2020/lib/audio/ui/container.mjs +0 -414
- package/esm2020/lib/audio/ui/scroll_pane_horizontal.mjs +0 -11
- package/esm2020/lib/audio/ui/sonagram.mjs +0 -900
- package/esm2020/lib/db/inddb.mjs +0 -120
- package/esm2020/lib/dsp/utils.mjs +0 -48
- package/esm2020/lib/io/BinaryWriter.mjs +0 -74
- package/esm2020/lib/math/complex.mjs +0 -58
- package/esm2020/lib/net/uploader.mjs +0 -367
- package/esm2020/lib/speechrecorder/project/project.mjs +0 -49
- package/esm2020/lib/speechrecorder/project/project.service.mjs +0 -64
- package/esm2020/lib/speechrecorder/recordings/basic_recording.service.mjs +0 -216
- package/esm2020/lib/speechrecorder/recordings/recordings.service.mjs +0 -1014
- package/esm2020/lib/speechrecorder/session/audiorecorder.mjs +0 -1179
- package/esm2020/lib/speechrecorder/session/basicrecorder.mjs +0 -666
- package/esm2020/lib/speechrecorder/session/controlpanel.mjs +0 -409
- package/esm2020/lib/speechrecorder/session/recording_file_cache.mjs +0 -195
- package/esm2020/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +0 -288
- package/esm2020/lib/speechrecorder/session/session.service.mjs +0 -69
- package/esm2020/lib/speechrecorder/session/sessionmanager.mjs +0 -1333
- package/esm2020/lib/speechrecorder/startstopsignal/ui/simpletrafficlight.mjs +0 -57
- package/esm2020/lib/ui/recordingitem_display.mjs +0 -253
- package/esm2020/lib/utils/ua-parser.mjs +0 -190
- package/esm2020/lib/utils/utils.mjs +0 -105
- package/esm2020/lib/utils/wake_lock.mjs +0 -114
- package/fesm2015/speechrecorderng.mjs +0 -17708
- package/fesm2015/speechrecorderng.mjs.map +0 -1
- package/fesm2020/speechrecorderng.mjs.map +0 -1
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import { RecordingFileUtils } from "../recording";
|
|
2
|
-
export class BasicRecFilesCache {
|
|
3
|
-
constructor() {
|
|
4
|
-
//public static readonly DEFAULT_MAX_SAMPLES=30*48000; // TEST 30 seconds
|
|
5
|
-
this._sampleCount = 0;
|
|
6
|
-
this.maxSampleCount = BasicRecFilesCache.DEFAULT_MAX_SAMPLES;
|
|
7
|
-
this._currentRecordingFile = null;
|
|
8
|
-
}
|
|
9
|
-
get currentRecordingFile() {
|
|
10
|
-
return this._currentRecordingFile;
|
|
11
|
-
}
|
|
12
|
-
set currentRecordingFile(value) {
|
|
13
|
-
this._currentRecordingFile = value;
|
|
14
|
-
this.expire();
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
BasicRecFilesCache.DEBUG = false;
|
|
18
|
-
BasicRecFilesCache.DEFAULT_MAX_SAMPLES = 10 * 60 * 48000; // 10 Minutes mono 48kHz
|
|
19
|
-
export class SprItemsCache extends BasicRecFilesCache {
|
|
20
|
-
constructor() {
|
|
21
|
-
super(...arguments);
|
|
22
|
-
this._items = new Array();
|
|
23
|
-
}
|
|
24
|
-
get items() {
|
|
25
|
-
return this._items;
|
|
26
|
-
}
|
|
27
|
-
addItem(item) {
|
|
28
|
-
this._items.push(item);
|
|
29
|
-
}
|
|
30
|
-
getItem(index) {
|
|
31
|
-
return this._items[index];
|
|
32
|
-
}
|
|
33
|
-
length() {
|
|
34
|
-
return this._items.length;
|
|
35
|
-
}
|
|
36
|
-
tryExpire(toBeExpiredRf) {
|
|
37
|
-
if (BasicRecFilesCache.DEBUG)
|
|
38
|
-
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " try expire:");
|
|
39
|
-
if (!RecordingFileUtils.equals(toBeExpiredRf, this.currentRecordingFile)) {
|
|
40
|
-
if (BasicRecFilesCache.DEBUG)
|
|
41
|
-
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " not current file...");
|
|
42
|
-
if (toBeExpiredRf.serverPersisted) {
|
|
43
|
-
if (BasicRecFilesCache.DEBUG)
|
|
44
|
-
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " is server persisted...");
|
|
45
|
-
// expire recording files first stored to the cache
|
|
46
|
-
let expiredSamples = RecordingFileUtils.expireAudioData(toBeExpiredRf);
|
|
47
|
-
this._sampleCount -= expiredSamples;
|
|
48
|
-
if (expiredSamples > 0) {
|
|
49
|
-
if (BasicRecFilesCache.DEBUG)
|
|
50
|
-
console.debug("Rec. files cache: Expired: " + toBeExpiredRf.toString() + ". Cache samples now: " + this._sampleCount);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
if (BasicRecFilesCache.DEBUG)
|
|
55
|
-
console.debug("Rec. files cache: #" + toBeExpiredRf.toString() + " not yet persisted on server.");
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
if (BasicRecFilesCache.DEBUG)
|
|
60
|
-
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " is current file.");
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
expire() {
|
|
64
|
-
// expire corrected versions first
|
|
65
|
-
if (BasicRecFilesCache.DEBUG)
|
|
66
|
-
console.debug("Rec. files cache: Expire? current: " + this._sampleCount + ", max: " + this.maxSampleCount);
|
|
67
|
-
if (this._sampleCount > this.maxSampleCount) {
|
|
68
|
-
// expire older versions of an item first
|
|
69
|
-
for (let ii = 0; ii < this._items.length; ii++) {
|
|
70
|
-
if (this._sampleCount <= this.maxSampleCount) {
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
let it = this._items[ii];
|
|
74
|
-
let itRfs = it.recs;
|
|
75
|
-
if (itRfs && itRfs.length > 1) {
|
|
76
|
-
for (let rfi = 0; rfi < itRfs.length - 1; rfi++) {
|
|
77
|
-
if (this._sampleCount <= this.maxSampleCount) {
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
let toBeExpiredRf = itRfs[rfi];
|
|
81
|
-
this.tryExpire(toBeExpiredRf);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// if that's not sufficient expire audio data of latest versions as well
|
|
86
|
-
for (let ii = 0; ii < this._items.length; ii++) {
|
|
87
|
-
if (this._sampleCount <= this.maxSampleCount) {
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
let it = this._items[ii];
|
|
91
|
-
let itRfs = it.recs;
|
|
92
|
-
if (itRfs && itRfs.length > 0) {
|
|
93
|
-
for (let rfi = 0; rfi < itRfs.length; rfi++) {
|
|
94
|
-
if (this._sampleCount <= this.maxSampleCount) {
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
let toBeExpiredRf = itRfs[rfi];
|
|
98
|
-
this.tryExpire(toBeExpiredRf);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
addSprRecFile(item, sprRecFile) {
|
|
105
|
-
this.expire();
|
|
106
|
-
if (!item.recs) {
|
|
107
|
-
item.recs = new Array();
|
|
108
|
-
}
|
|
109
|
-
item.recs[sprRecFile.version] = sprRecFile;
|
|
110
|
-
this._sampleCount += RecordingFileUtils.sampleCount(sprRecFile);
|
|
111
|
-
if (BasicRecFilesCache.DEBUG)
|
|
112
|
-
console.debug("Rec. files cache: Added. Cache samples: " + this._sampleCount);
|
|
113
|
-
}
|
|
114
|
-
setSprRecFileAudioData(sprRecFile, adh) {
|
|
115
|
-
this.expire();
|
|
116
|
-
if (BasicRecFilesCache.DEBUG)
|
|
117
|
-
console.debug("Rec. files cache: Set audio data after expire. Cache samples: " + this._sampleCount);
|
|
118
|
-
let currSampleCnt = RecordingFileUtils.sampleCount(sprRecFile);
|
|
119
|
-
this._sampleCount -= currSampleCnt;
|
|
120
|
-
if (BasicRecFilesCache.DEBUG)
|
|
121
|
-
console.debug("Rec. files cache: Set audio data subtracted curr sample count: " + currSampleCnt + ". Cache samples: " + this._sampleCount);
|
|
122
|
-
RecordingFileUtils.setAudioData(sprRecFile, adh);
|
|
123
|
-
let newSampleCnt = RecordingFileUtils.sampleCount(sprRecFile);
|
|
124
|
-
this._sampleCount += newSampleCnt;
|
|
125
|
-
if (BasicRecFilesCache.DEBUG)
|
|
126
|
-
console.debug("Rec. files cache: Set audio data added new sample count: " + newSampleCnt + ". Cache samples: " + this._sampleCount);
|
|
127
|
-
let fl = adh?.frameLen;
|
|
128
|
-
if (sprRecFile.frames == null && fl) {
|
|
129
|
-
sprRecFile.frames = fl;
|
|
130
|
-
}
|
|
131
|
-
if (BasicRecFilesCache.DEBUG)
|
|
132
|
-
console.debug("Rec. files cache: Set audio data. Cache samples: " + this._sampleCount);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
export class RecFilesCache extends BasicRecFilesCache {
|
|
136
|
-
constructor() {
|
|
137
|
-
super(...arguments);
|
|
138
|
-
this._recFiles = new Array();
|
|
139
|
-
}
|
|
140
|
-
get recFiles() {
|
|
141
|
-
return this._recFiles;
|
|
142
|
-
}
|
|
143
|
-
getRecFile(index) {
|
|
144
|
-
return this._recFiles[index];
|
|
145
|
-
}
|
|
146
|
-
length() {
|
|
147
|
-
return this._recFiles.length;
|
|
148
|
-
}
|
|
149
|
-
expire() {
|
|
150
|
-
if (this._sampleCount > this.maxSampleCount) {
|
|
151
|
-
// audio recorder list is sorted: lower index is newer
|
|
152
|
-
for (let rfI = this._recFiles.length - 1; rfI >= 0; rfI--) {
|
|
153
|
-
if (this._sampleCount <= this.maxSampleCount) {
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
let toBeExpiredRf = this._recFiles[rfI];
|
|
157
|
-
if (toBeExpiredRf.serverPersisted) {
|
|
158
|
-
if (!RecordingFileUtils.equals(toBeExpiredRf, this.currentRecordingFile)) {
|
|
159
|
-
// expire recording files first stored to the cache
|
|
160
|
-
let expiredSamples = RecordingFileUtils.expireAudioData(toBeExpiredRf);
|
|
161
|
-
this._sampleCount -= expiredSamples;
|
|
162
|
-
if (expiredSamples > 0) {
|
|
163
|
-
if (BasicRecFilesCache.DEBUG)
|
|
164
|
-
console.debug("Rec. files cache: Expired #" + rfI + ". Cache samples: " + this._sampleCount);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
if (BasicRecFilesCache.DEBUG)
|
|
169
|
-
console.debug("Rec. files cache: #" + rfI + " is current file. (not expiring)");
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
if (BasicRecFilesCache.DEBUG)
|
|
174
|
-
console.debug("Rec. files cache: #" + rfI + " not yet server persisted.");
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
addRecFile(recFile) {
|
|
180
|
-
this.expire();
|
|
181
|
-
this._recFiles.push(recFile);
|
|
182
|
-
this._sampleCount += RecordingFileUtils.sampleCount(recFile);
|
|
183
|
-
if (BasicRecFilesCache.DEBUG)
|
|
184
|
-
console.debug("Rec. files cache: Added. Cache samples: " + this._sampleCount);
|
|
185
|
-
}
|
|
186
|
-
setRecFileAudioData(recFile, adh) {
|
|
187
|
-
this.expire();
|
|
188
|
-
this._sampleCount -= RecordingFileUtils.sampleCount(recFile);
|
|
189
|
-
RecordingFileUtils.setAudioData(recFile, adh);
|
|
190
|
-
this._sampleCount += RecordingFileUtils.sampleCount(recFile);
|
|
191
|
-
if (BasicRecFilesCache.DEBUG)
|
|
192
|
-
console.debug("Rec. files cache: Set audio data. Cache samples: " + this._sampleCount);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3JkaW5nX2ZpbGVfY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zcGVlY2hyZWNvcmRlcm5nL3NyYy9saWIvc3BlZWNocmVjb3JkZXIvc2Vzc2lvbi9yZWNvcmRpbmdfZmlsZV9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWdCLGtCQUFrQixFQUFtQixNQUFNLGNBQWMsQ0FBQztBQUlqRixNQUFNLE9BQWdCLGtCQUFrQjtJQUF4QztRQUtFLDBFQUEwRTtRQUVoRSxpQkFBWSxHQUFRLENBQUMsQ0FBQztRQUNoQyxtQkFBYyxHQUFRLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDO1FBQ3JELDBCQUFxQixHQUFvQixJQUFJLENBQUM7SUFXeEQsQ0FBQztJQVJDLElBQUksb0JBQW9CO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLHFCQUFxQixDQUFDO0lBQ3BDLENBQUM7SUFFRCxJQUFJLG9CQUFvQixDQUFDLEtBQTJCO1FBQ2xELElBQUksQ0FBQyxxQkFBcUIsR0FBRyxLQUFLLENBQUM7UUFDbkMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ2hCLENBQUM7O0FBakJzQix3QkFBSyxHQUFDLEtBQUssQ0FBQztBQUNaLHNDQUFtQixHQUFDLEVBQUUsR0FBQyxFQUFFLEdBQUMsS0FBSyxDQUFDLENBQUUsd0JBQXdCO0FBcUJuRixNQUFNLE9BQU8sYUFBYyxTQUFRLGtCQUFrQjtJQUFyRDs7UUFHWSxXQUFNLEdBQWEsSUFBSSxLQUFLLEVBQVEsQ0FBQztJQThHakQsQ0FBQztJQTVHRyxJQUFJLEtBQUs7UUFDTCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDdkIsQ0FBQztJQUVELE9BQU8sQ0FBQyxJQUFTO1FBQ2IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUVELE9BQU8sQ0FBQyxLQUFZO1FBQ2hC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QyxPQUFPLENBQUMsQ0FBQztRQUMzRCxJQUFHLGtCQUFrQixDQUFDLEtBQUs7WUFBQyxPQUFPLENBQUMsS0FBSyxDQUFDLG1EQUFtRCxHQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNuSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1JlY29yZGluZ0ZpbGUsIFJlY29yZGluZ0ZpbGVVdGlscywgU3ByUmVjb3JkaW5nRmlsZX0gZnJvbSBcIi4uL3JlY29yZGluZ1wiO1xyXG5pbXBvcnQge0l0ZW19IGZyb20gXCIuL2l0ZW1cIjtcclxuaW1wb3J0IHtBdWRpb0RhdGFIb2xkZXJ9IGZyb20gXCIuLi8uLi9hdWRpby9hdWRpb19kYXRhX2hvbGRlclwiO1xyXG5cclxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2ljUmVjRmlsZXNDYWNoZSB7XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREVCVUc9ZmFsc2U7XHJcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX01BWF9TQU1QTEVTPTEwKjYwKjQ4MDAwOyAgLy8gMTAgTWludXRlcyBtb25vIDQ4a0h6XHJcblxyXG4gIC8vcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX01BWF9TQU1QTEVTPTMwKjQ4MDAwOyAgLy8gVEVTVCAzMCBzZWNvbmRzXHJcblxyXG4gIHByb3RlY3RlZCBfc2FtcGxlQ291bnQ6bnVtYmVyPTA7XHJcbiAgbWF4U2FtcGxlQ291bnQ6bnVtYmVyPUJhc2ljUmVjRmlsZXNDYWNoZS5ERUZBVUxUX01BWF9TQU1QTEVTO1xyXG4gIHByaXZhdGUgX2N1cnJlbnRSZWNvcmRpbmdGaWxlOlJlY29yZGluZ0ZpbGV8bnVsbD1udWxsO1xyXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBleHBpcmUoKTp2b2lkO1xyXG5cclxuICBnZXQgY3VycmVudFJlY29yZGluZ0ZpbGUoKTogUmVjb3JkaW5nRmlsZSB8IG51bGwge1xyXG4gICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRSZWNvcmRpbmdGaWxlO1xyXG4gIH1cclxuXHJcbiAgc2V0IGN1cnJlbnRSZWNvcmRpbmdGaWxlKHZhbHVlOiBSZWNvcmRpbmdGaWxlIHwgbnVsbCkge1xyXG4gICAgdGhpcy5fY3VycmVudFJlY29yZGluZ0ZpbGUgPSB2YWx1ZTtcclxuICAgIHRoaXMuZXhwaXJlKCk7XHJcbiAgfVxyXG59XHJcblxyXG5cclxuXHJcbmV4cG9ydCBjbGFzcyBTcHJJdGVtc0NhY2hlIGV4dGVuZHMgQmFzaWNSZWNGaWxlc0NhY2hle1xyXG5cclxuXHJcbiAgICBwcml2YXRlIF9pdGVtczpBcnJheTxJdGVtPj1uZXcgQXJyYXk8SXRlbT4oKTtcclxuXHJcbiAgICBnZXQgaXRlbXMoKTogQXJyYXk8SXRlbT4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9pdGVtcztcclxuICAgIH1cclxuXHJcbiAgICBhZGRJdGVtKGl0ZW06SXRlbSl7XHJcbiAgICAgICAgdGhpcy5faXRlbXMucHVzaChpdGVtKTtcclxuICAgIH1cclxuXHJcbiAgICBnZXRJdGVtKGluZGV4Om51bWJlcil7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2l0ZW1zW2luZGV4XTtcclxuICAgIH1cclxuXHJcbiAgICBsZW5ndGgoKTpudW1iZXJ7XHJcbiAgICAgICByZXR1cm4gdGhpcy5faXRlbXMubGVuZ3RoO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICBwcml2YXRlIHRyeUV4cGlyZSh0b0JlRXhwaXJlZFJmOlNwclJlY29yZGluZ0ZpbGUpe1xyXG4gICAgICBpZihCYXNpY1JlY0ZpbGVzQ2FjaGUuREVCVUcpY29uc29sZS5kZWJ1ZyhcIlJlYy4gZmlsZXMgY2FjaGU6IFwiICsgdG9CZUV4cGlyZWRSZi50b1N0cmluZygpK1wiIHRyeSBleHBpcmU6XCIpO1xyXG4gICAgICBpZighUmVjb3JkaW5nRmlsZVV0aWxzLmVxdWFscyh0b0JlRXhwaXJlZFJmLHRoaXMuY3VycmVudFJlY29yZGluZ0ZpbGUpKSB7XHJcbiAgICAgICAgaWYoQmFzaWNSZWNGaWxlc0NhY2hlLkRFQlVHKWNvbnNvbGUuZGVidWcoXCJSZWMuIGZpbGVzIGNhY2hlOiBcIiArIHRvQmVFeHBpcmVkUmYudG9TdHJpbmcoKStcIiBub3QgY3VycmVudCBmaWxlLi4uXCIpO1xyXG4gICAgICAgIGlmICh0b0JlRXhwaXJlZFJmLnNlcnZlclBlcnNpc3RlZCkge1xyXG4gICAgICAgICAgaWYoQmFzaWNSZWNGaWxlc0NhY2hlLkRFQlVHKWNvbnNvbGUuZGVidWcoXCJSZWMuIGZpbGVzIGNhY2hlOiBcIiArIHRvQmVFeHBpcmVkUmYudG9TdHJpbmcoKStcIiBpcyBzZXJ2ZXIgcGVyc2lzdGVkLi4uXCIpO1xyXG4gICAgICAgICAgLy8gZXhwaXJlIHJlY29yZGluZyBmaWxlcyBmaXJzdCBzdG9yZWQgdG8gdGhlIGNhY2hlXHJcbiAgICAgICAgICBsZXQgZXhwaXJlZFNhbXBsZXMgPSBSZWNvcmRpbmdGaWxlVXRpbHMuZXhwaXJlQXVkaW9EYXRhKHRvQmVFeHBpcmVkUmYpO1xyXG4gICAgICAgICAgdGhpcy5fc2FtcGxlQ291bnQgLT0gZXhwaXJlZFNhbXBsZXM7XHJcbiAgICAgICAgICBpZihleHBpcmVkU2FtcGxlcz4wKSB7XHJcbiAgICAgICAgICAgIGlmIChCYXNpY1JlY0ZpbGVzQ2FjaGUuREVCVUcpIGNvbnNvbGUuZGVidWcoXCJSZWMuIGZpbGVzIGNhY2hlOiBFeHBpcmVkOiBcIiArIHRvQmVFeHBpcmVkUmYudG9TdHJpbmcoKSArIFwiLiBDYWNoZSBzYW1wbGVzIG5vdzogXCIgKyB0aGlzLl9zYW1wbGVDb3VudCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGlmKEJhc2ljUmVjRmlsZXNDYWNoZS5ERUJVRyljb25zb2xlLmRlYnVnKFwiUmVjLiBmaWxlcyBjYWNoZTogI1wiICsgdG9CZUV4cGlyZWRSZi50b1N0cmluZygpICsgXCIgbm90IHlldCBwZXJzaXN0ZWQgb24gc2VydmVyLlwiKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1lbHNle1xyXG4gICAgICAgIGlmKEJhc2ljUmVjRmlsZXNDYWNoZS5ERUJVRyljb25zb2xlLmRlYnVnKFwiUmVjLiBmaWxlcyBjYWNoZTogXCIgKyB0b0JlRXhwaXJlZFJmLnRvU3RyaW5nKCkrXCIgaXMgY3VycmVudCBmaWxlLlwiKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICBwcm90ZWN0ZWQgZXhwaXJlKCkge1xyXG4gICAgLy8gZXhwaXJlIGNvcnJlY3RlZCB2ZXJzaW9ucyBmaXJzdFxyXG4gICAgaWYoQmFzaWNSZWNGaWxlc0NhY2hlLkRFQlVHKWNvbnNvbGUuZGVidWcoXCJSZWMuIGZpbGVzIGNhY2hlOiBFeHBpcmU/IGN1cnJlbnQ6IFwiK3RoaXMuX3NhbXBsZUNvdW50K1wiLCBtYXg6IFwiK3RoaXMubWF4U2FtcGxlQ291bnQpO1xyXG4gICAgaWYgKHRoaXMuX3NhbXBsZUNvdW50ID4gdGhpcy5tYXhTYW1wbGVDb3VudCkge1xyXG5cclxuICAgICAgLy8gZXhwaXJlIG9sZGVyIHZlcnNpb25zIG9mIGFuIGl0ZW0gZmlyc3RcclxuICAgICAgZm9yIChsZXQgaWkgPSAwOyBpaSA8IHRoaXMuX2l0ZW1zLmxlbmd0aDsgaWkrKykge1xyXG4gICAgICAgIGlmICh0aGlzLl9zYW1wbGVDb3VudCA8PSB0aGlzLm1heFNhbXBsZUNvdW50KSB7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgICAgbGV0IGl0ID0gdGhpcy5faXRlbXNbaWldO1xyXG4gICAgICAgIGxldCBpdFJmcyA9IGl0LnJlY3M7XHJcblxyXG4gICAgICAgIGlmIChpdFJmcyAmJiBpdFJmcy5sZW5ndGggPiAxKSB7XHJcbiAgICAgICAgICBmb3IgKGxldCByZmkgPSAwOyByZmkgPCBpdFJmcy5sZW5ndGggLSAxOyByZmkrKykge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5fc2FtcGxlQ291bnQgPD0gdGhpcy5tYXhTYW1wbGVDb3VudCkge1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGxldCB0b0JlRXhwaXJlZFJmID0gaXRSZnNbcmZpXTtcclxuICAgICAgICAgICAgdGhpcy50cnlFeHBpcmUodG9CZUV4cGlyZWRSZik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBpZiB0aGF0J3Mgbm90IHN1ZmZpY2llbnQgZXhwaXJlIGF1ZGlvIGRhdGEgb2YgbGF0ZXN0IHZlcnNpb25zIGFzIHdlbGxcclxuICAgICAgZm9yIChsZXQgaWkgPSAwOyBpaSA8IHRoaXMuX2l0ZW1zLmxlbmd0aDsgaWkrKykge1xyXG4gICAgICAgIGlmICh0aGlzLl9zYW1wbGVDb3VudCA8PSB0aGlzLm1heFNhbXBsZUNvdW50KSB7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgICAgbGV0IGl0ID0gdGhpcy5faXRlbXNbaWldO1xyXG4gICAgICAgIGxldCBpdFJmcyA9IGl0LnJlY3M7XHJcblxyXG4gICAgICAgIGlmIChpdFJmcyAmJiBpdFJmcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICBmb3IgKGxldCByZmkgPSAwOyByZmkgPCBpdFJmcy5sZW5ndGg7IHJmaSsrKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9zYW1wbGVDb3VudCA8PSB0aGlzLm1heFNhbXBsZUNvdW50KSB7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgbGV0IHRvQmVFeHBpcmVkUmYgPSBpdFJmc1tyZmldO1xyXG4gICAgICAgICAgICB0aGlzLnRyeUV4cGlyZSh0b0JlRXhwaXJlZFJmKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFkZFNwclJlY0ZpbGUoaXRlbTpJdGVtLHNwclJlY0ZpbGU6U3ByUmVjb3JkaW5nRmlsZSl7XHJcbiAgICB0aGlzLmV4cGlyZSgpO1xyXG4gICAgaWYoIWl0ZW0ucmVjcykge1xyXG4gICAgICBpdGVtLnJlY3M9bmV3IEFycmF5PFNwclJlY29yZGluZ0ZpbGU+KCk7XHJcbiAgICB9XHJcbiAgICBpdGVtLnJlY3Nbc3ByUmVjRmlsZS52ZXJzaW9uXT1zcHJSZWNGaWxlO1xyXG4gICAgdGhpcy5fc2FtcGxlQ291bnQgKz0gUmVjb3JkaW5nRmlsZVV0aWxzLnNhbXBsZUNvdW50KHNwclJlY0ZpbGUpO1xyXG4gICAgaWYoQmFzaWNSZWNGaWxlc0NhY2hlLkRFQlVHKWNvbnNvbGUuZGVidWcoXCJSZWMuIGZpbGVzIGNhY2hlOiBBZGRlZC4gQ2FjaGUgc2FtcGxlczogXCIrdGhpcy5fc2FtcGxlQ291bnQpO1xyXG4gIH1cclxuXHJcbiAgc2V0U3ByUmVjRmlsZUF1ZGlvRGF0YShzcHJSZWNGaWxlOlNwclJlY29yZGluZ0ZpbGUsIGFkaDpBdWRpb0RhdGFIb2xkZXJ8bnVsbCl7XHJcbiAgICB0aGlzLmV4cGlyZSgpO1xyXG4gICAgaWYoQmFzaWNSZWNGaWxlc0NhY2hlLkRFQlVHKWNvbnNvbGUuZGVidWcoXCJSZWMuIGZpbGVzIGNhY2hlOiBTZXQgYXVkaW8gZGF0YSBhZnRlciBleHBpcmUuIENhY2hlIHNhbXBsZXM6IFwiK3RoaXMuX3NhbXBsZUNvdW50KTtcclxuICAgIGxldCBjdXJyU2FtcGxlQ250PVJlY29yZGluZ0ZpbGVVdGlscy5zYW1wbGVDb3VudChzcHJSZWNGaWxlKTtcclxuICAgIHRoaXMuX3NhbXBsZUNvdW50LT1jdXJyU2FtcGxlQ250O1xyXG4gICAgaWYoQmFzaWNSZWNGaWxlc0NhY2hlLkRFQlVHKWNvbnNvbGUuZGVidWcoXCJSZWMuIGZpbGVzIGNhY2hlOiBTZXQgYXVkaW8gZGF0YSBzdWJ0cmFjdGVkIGN1cnIgc2FtcGxlIGNvdW50OiBcIitjdXJyU2FtcGxlQ250K1wiLiBDYWNoZSBzYW1wbGVzOiBcIit0aGlzLl9zYW1wbGVDb3VudCk7XHJcbiAgICBSZWNvcmRpbmdGaWxlVXRpbHMuc2V0QXVkaW9EYXRhKHNwclJlY0ZpbGUsYWRoKTtcclxuICAgIGxldCBuZXdTYW1wbGVDbnQ9UmVjb3JkaW5nRmlsZVV0aWxzLnNhbXBsZUNvdW50KHNwclJlY0ZpbGUpO1xyXG4gICAgdGhpcy5fc2FtcGxlQ291bnQrPW5ld1NhbXBsZUNudDtcclxuICAgIGlmKEJhc2ljUmVjRmlsZXNDYWNoZS5ERUJVRyljb25zb2xlLmRlYnVnKFwiUmVjLiBmaWxlcyBjYWNoZTogU2V0IGF1ZGlvIGRhdGEgYWRkZWQgbmV3IHNhbXBsZSBjb3VudDogXCIrbmV3U2FtcGxlQ250K1wiLiBDYWNoZSBzYW1wbGVzOiBcIit0aGlzLl9zYW1wbGVDb3VudCk7XHJcbiAgICBsZXQgZmw9YWRoPy5mcmFtZUxlbjtcclxuICAgIGlmKHNwclJlY0ZpbGUuZnJhbWVzPT1udWxsICYmIGZsKXtcclxuICAgICAgc3ByUmVjRmlsZS5mcmFtZXM9Zmw7XHJcbiAgICB9XHJcbiAgICBpZihCYXNpY1JlY0ZpbGVzQ2FjaGUuREVCVUcpY29uc29sZS5kZWJ1ZyhcIlJlYy4gZmlsZXMgY2FjaGU6IFNldCBhdWRpbyBkYXRhLiBDYWNoZSBzYW1wbGVzOiBcIit0aGlzLl9zYW1wbGVDb3VudCk7XHJcbiAgfVxyXG59XHJcblxyXG5cclxuZXhwb3J0IGNsYXNzIFJlY0ZpbGVzQ2FjaGUgZXh0ZW5kcyBCYXNpY1JlY0ZpbGVzQ2FjaGV7XHJcblxyXG4gIHByaXZhdGUgX3JlY0ZpbGVzOkFycmF5PFJlY29yZGluZ0ZpbGU+PW5ldyBBcnJheTxSZWNvcmRpbmdGaWxlPigpO1xyXG5cclxuICBnZXQgcmVjRmlsZXMoKTogQXJyYXk8UmVjb3JkaW5nRmlsZT4ge1xyXG4gICAgcmV0dXJuIHRoaXMuX3JlY0ZpbGVzO1xyXG4gIH1cclxuXHJcbiAgZ2V0UmVjRmlsZShpbmRleDpudW1iZXIpe1xyXG4gICAgcmV0dXJuIHRoaXMuX3JlY0ZpbGVzW2luZGV4XTtcclxuICB9XHJcblxyXG4gIGxlbmd0aCgpOm51bWJlcntcclxuICAgIHJldHVybiB0aGlzLl9yZWNGaWxlcy5sZW5ndGg7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgZXhwaXJlKCkge1xyXG4gICAgaWYgKHRoaXMuX3NhbXBsZUNvdW50ID4gdGhpcy5tYXhTYW1wbGVDb3VudCkge1xyXG4gICAgICAvLyBhdWRpbyByZWNvcmRlciBsaXN0IGlzIHNvcnRlZDogbG93ZXIgaW5kZXggaXMgbmV3ZXJcclxuICAgICAgZm9yIChsZXQgcmZJID0gdGhpcy5fcmVjRmlsZXMubGVuZ3RoLTE7IHJmSSA+PTA7IHJmSS0tKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX3NhbXBsZUNvdW50IDw9IHRoaXMubWF4U2FtcGxlQ291bnQpIHtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgICBsZXQgdG9CZUV4cGlyZWRSZiA9IHRoaXMuX3JlY0ZpbGVzW3JmSV07XHJcbiAgICAgICAgaWYgKHRvQmVFeHBpcmVkUmYuc2VydmVyUGVyc2lzdGVkKSB7XHJcbiAgICAgICAgICBpZighUmVjb3JkaW5nRmlsZVV0aWxzLmVxdWFscyh0b0JlRXhwaXJlZFJmLHRoaXMuY3VycmVudFJlY29yZGluZ0ZpbGUpKSB7XHJcbiAgICAgICAgICAgIC8vIGV4cGlyZSByZWNvcmRpbmcgZmlsZXMgZmlyc3Qgc3RvcmVkIHRvIHRoZSBjYWNoZVxyXG4gICAgICAgICAgICBsZXQgZXhwaXJlZFNhbXBsZXMgPSBSZWNvcmRpbmdGaWxlVXRpbHMuZXhwaXJlQXVkaW9EYXRhKHRvQmVFeHBpcmVkUmYpO1xyXG4gICAgICAgICAgICB0aGlzLl9zYW1wbGVDb3VudCAtPSBleHBpcmVkU2FtcGxlcztcclxuICAgICAgICAgICAgaWYoZXhwaXJlZFNhbXBsZXM+MCkge1xyXG4gICAgICAgICAgICAgIGlmIChCYXNpY1JlY0ZpbGVzQ2FjaGUuREVCVUcpIGNvbnNvbGUuZGVidWcoXCJSZWMuIGZpbGVzIGNhY2hlOiBFeHBpcmVkICNcIiArIHJmSSArIFwiLiBDYWNoZSBzYW1wbGVzOiBcIiArIHRoaXMuX3NhbXBsZUNvdW50KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfWVsc2V7XHJcbiAgICAgICAgICAgIGlmKEJhc2ljUmVjRmlsZXNDYWNoZS5ERUJVRyljb25zb2xlLmRlYnVnKFwiUmVjLiBmaWxlcyBjYWNoZTogI1wiK3JmSStcIiBpcyBjdXJyZW50IGZpbGUuIChub3QgZXhwaXJpbmcpXCIpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1lbHNle1xyXG4gICAgICAgICAgaWYoQmFzaWNSZWNGaWxlc0NhY2hlLkRFQlVHKWNvbnNvbGUuZGVidWcoXCJSZWMuIGZpbGVzIGNhY2hlOiAjXCIrcmZJK1wiIG5vdCB5ZXQgc2VydmVyIHBlcnNpc3RlZC5cIik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhZGRSZWNGaWxlKHJlY0ZpbGU6UmVjb3JkaW5nRmlsZSl7XHJcbiAgICB0aGlzLmV4cGlyZSgpO1xyXG4gICAgdGhpcy5fcmVjRmlsZXMucHVzaChyZWNGaWxlKTtcclxuICAgIHRoaXMuX3NhbXBsZUNvdW50ICs9IFJlY29yZGluZ0ZpbGVVdGlscy5zYW1wbGVDb3VudChyZWNGaWxlKTtcclxuICAgIGlmKEJhc2ljUmVjRmlsZXNDYWNoZS5ERUJVRyljb25zb2xlLmRlYnVnKFwiUmVjLiBmaWxlcyBjYWNoZTogQWRkZWQuIENhY2hlIHNhbXBsZXM6IFwiK3RoaXMuX3NhbXBsZUNvdW50KTtcclxuICB9XHJcblxyXG4gIHNldFJlY0ZpbGVBdWRpb0RhdGEocmVjRmlsZTpSZWNvcmRpbmdGaWxlLCBhZGg6QXVkaW9EYXRhSG9sZGVyfG51bGwpe1xyXG4gICAgdGhpcy5leHBpcmUoKTtcclxuICAgIHRoaXMuX3NhbXBsZUNvdW50LT1SZWNvcmRpbmdGaWxlVXRpbHMuc2FtcGxlQ291bnQocmVjRmlsZSk7XHJcbiAgICBSZWNvcmRpbmdGaWxlVXRpbHMuc2V0QXVkaW9EYXRhKHJlY0ZpbGUsYWRoKTtcclxuICAgIHRoaXMuX3NhbXBsZUNvdW50Kz1SZWNvcmRpbmdGaWxlVXRpbHMuc2FtcGxlQ291bnQocmVjRmlsZSk7XHJcbiAgICBpZihCYXNpY1JlY0ZpbGVzQ2FjaGUuREVCVUcpY29uc29sZS5kZWJ1ZyhcIlJlYy4gZmlsZXMgY2FjaGU6IFNldCBhdWRpbyBkYXRhLiBDYWNoZSBzYW1wbGVzOiBcIit0aGlzLl9zYW1wbGVDb3VudCk7XHJcbiAgfVxyXG59XHJcblxyXG4iXX0=
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import { Inject, Injectable } from '@angular/core';
|
|
2
|
-
import { HttpHeaders } from "@angular/common/http";
|
|
3
|
-
import { Observable } from "rxjs";
|
|
4
|
-
import { ApiType, SPEECHRECORDER_CONFIG } from "../../../spr.config";
|
|
5
|
-
import { UUID } from "../../../utils/utils";
|
|
6
|
-
import { RecordingFileUtils } from "../../recording";
|
|
7
|
-
import { AudioBufferSource, AudioDataHolder } from "../../../audio/audio_data_holder";
|
|
8
|
-
import { BasicRecordingService } from "../../recordings/basic_recording.service";
|
|
9
|
-
import { AudioContextProvider } from "../../../audio/context";
|
|
10
|
-
import * as i0 from "@angular/core";
|
|
11
|
-
import * as i1 from "@angular/common/http";
|
|
12
|
-
import * as i2 from "../../../spr.config";
|
|
13
|
-
export class RecordingFileService extends BasicRecordingService {
|
|
14
|
-
constructor(http, config) {
|
|
15
|
-
super(http, config);
|
|
16
|
-
this.http = http;
|
|
17
|
-
this.config = config;
|
|
18
|
-
//private debugDelay:number=10000;
|
|
19
|
-
this.debugDelay = 0;
|
|
20
|
-
}
|
|
21
|
-
recoFileUrl(recordingFileId) {
|
|
22
|
-
let encRecfileId = encodeURIComponent(recordingFileId);
|
|
23
|
-
let recUrl = this.apiEndPoint + RecordingFileService.RECOFILE_API_CTX + '/' + encRecfileId;
|
|
24
|
-
return recUrl;
|
|
25
|
-
}
|
|
26
|
-
fetchAudiofile(recordingFileId) {
|
|
27
|
-
let recUrl = this.recoFileUrl(recordingFileId);
|
|
28
|
-
if (this.config && this.config.apiType === ApiType.FILES) {
|
|
29
|
-
// for development and demo
|
|
30
|
-
// append UUID to make request URL unique to avoid localhost server caching
|
|
31
|
-
recUrl = recUrl + '.wav';
|
|
32
|
-
}
|
|
33
|
-
let headers = new HttpHeaders({
|
|
34
|
-
'Accept': 'audio/wav'
|
|
35
|
-
});
|
|
36
|
-
return this.http.get(recUrl, {
|
|
37
|
-
observe: 'response',
|
|
38
|
-
headers: headers,
|
|
39
|
-
responseType: 'arraybuffer',
|
|
40
|
-
withCredentials: this.withCredentials
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
recordingFileDescrObserver(recordingFileId) {
|
|
44
|
-
let recUrl = this.recoFileUrl(recordingFileId);
|
|
45
|
-
if (this.config && this.config.apiType === ApiType.FILES) {
|
|
46
|
-
// for development and demo
|
|
47
|
-
// append UUID to make request URL unique to avoid localhost server caching
|
|
48
|
-
recUrl = recUrl + '.json?requestUUID=' + UUID.generate();
|
|
49
|
-
}
|
|
50
|
-
return this.http.get(recUrl, { withCredentials: this.withCredentials });
|
|
51
|
-
}
|
|
52
|
-
sprRecordingFileDescrObserver(recordingFileId) {
|
|
53
|
-
let recUrl = this.recoFileUrl(recordingFileId);
|
|
54
|
-
if (this.config && this.config.apiType === ApiType.FILES) {
|
|
55
|
-
// for development and demo
|
|
56
|
-
// append UUID to make request URL unique to avoid localhost server caching
|
|
57
|
-
recUrl = recUrl + '.json?requestUUID=' + UUID.generate();
|
|
58
|
-
}
|
|
59
|
-
return this.http.get(recUrl, { withCredentials: this.withCredentials });
|
|
60
|
-
}
|
|
61
|
-
fetchSessionAudiofileById(projectName, sessId, recordingFileId) {
|
|
62
|
-
let recUrl = this.recoFileUrl(recordingFileId);
|
|
63
|
-
// if (this.config && this.config.apiType === ApiType.FILES) {
|
|
64
|
-
// // for development and demo
|
|
65
|
-
// // append UUID to make request URL unique to avoid localhost server caching
|
|
66
|
-
// recUrl = recUrl + '.wav?requestUUID=' + UUID.generate();
|
|
67
|
-
// }
|
|
68
|
-
return this.http.get(recUrl, {
|
|
69
|
-
observe: 'response',
|
|
70
|
-
responseType: 'arraybuffer',
|
|
71
|
-
withCredentials: this.withCredentials
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
// TODO test
|
|
75
|
-
fetchAndApplyRecordingFile(recordingFile) {
|
|
76
|
-
let wobs = new Observable(observer => {
|
|
77
|
-
if (recordingFile.recordingFileId) {
|
|
78
|
-
let obs = this.fetchAudiofile(recordingFile.recordingFileId);
|
|
79
|
-
obs.subscribe({ next: resp => {
|
|
80
|
-
if (resp.body) {
|
|
81
|
-
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
82
|
-
let as = new AudioBufferSource(ab);
|
|
83
|
-
RecordingFileUtils.setAudioData(recordingFile, new AudioDataHolder(as));
|
|
84
|
-
if (this.debugDelay > 0) {
|
|
85
|
-
window.setTimeout(() => {
|
|
86
|
-
observer.next(recordingFile);
|
|
87
|
-
observer.complete();
|
|
88
|
-
}, this.debugDelay);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
observer.next(recordingFile);
|
|
92
|
-
observer.complete();
|
|
93
|
-
}
|
|
94
|
-
}).catch(reason => { observer.error(reason); });
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
observer.error('Received no audio data!');
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
error: (error) => {
|
|
101
|
-
if (error.status == 404) {
|
|
102
|
-
// Interpret not as an error, the file ist not recorded yet
|
|
103
|
-
observer.next(null);
|
|
104
|
-
observer.complete();
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
// all other states are errors
|
|
108
|
-
observer.error(error);
|
|
109
|
-
observer.complete();
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
observer.error();
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
return wobs;
|
|
119
|
-
}
|
|
120
|
-
fetchRecordingFile(aCtx, recordingFileId) {
|
|
121
|
-
let wobs = new Observable(observer => {
|
|
122
|
-
let rf = null;
|
|
123
|
-
let rfDescrObs = this.recordingFileDescrObserver(recordingFileId);
|
|
124
|
-
rfDescrObs.subscribe({ next: value => {
|
|
125
|
-
rf = value;
|
|
126
|
-
}, error: (error) => {
|
|
127
|
-
observer.error(error);
|
|
128
|
-
}, complete: () => {
|
|
129
|
-
let rfAudioObs = this.fetchAudiofile(recordingFileId);
|
|
130
|
-
rfAudioObs.subscribe({
|
|
131
|
-
next: resp => {
|
|
132
|
-
// Do not use Promise version, which does not work with Safari 13
|
|
133
|
-
if (resp.body) {
|
|
134
|
-
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
135
|
-
if (rf) {
|
|
136
|
-
let as = new AudioBufferSource(ab);
|
|
137
|
-
RecordingFileUtils.setAudioData(rf, new AudioDataHolder(as));
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
observer.error('Recording file object null');
|
|
141
|
-
}
|
|
142
|
-
if (this.debugDelay > 0) {
|
|
143
|
-
window.setTimeout(() => {
|
|
144
|
-
observer.next(rf);
|
|
145
|
-
observer.complete();
|
|
146
|
-
}, this.debugDelay);
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
observer.next(rf);
|
|
150
|
-
observer.complete();
|
|
151
|
-
}
|
|
152
|
-
}).catch(reason => { observer.error(reason); });
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
observer.error('Received no audio data');
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
error: (error) => {
|
|
159
|
-
if (error.status == 404) {
|
|
160
|
-
// Interpret not as an error, the file ist not recorded yet
|
|
161
|
-
observer.next(null);
|
|
162
|
-
observer.complete();
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
// all other states are errors
|
|
166
|
-
observer.error(error);
|
|
167
|
-
observer.complete();
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
return wobs;
|
|
175
|
-
}
|
|
176
|
-
fetchSprRecordingFile(recordingFileId) {
|
|
177
|
-
let wobs = new Observable(observer => {
|
|
178
|
-
let rf = null;
|
|
179
|
-
let rfDescrObs = this.sprRecordingFileDescrObserver(recordingFileId);
|
|
180
|
-
rfDescrObs.subscribe({ next: value => {
|
|
181
|
-
rf = value;
|
|
182
|
-
},
|
|
183
|
-
error: (error) => {
|
|
184
|
-
observer.error(error);
|
|
185
|
-
}, complete: () => {
|
|
186
|
-
let sampleCnt = null;
|
|
187
|
-
if (rf && rf.channels && rf.frames) {
|
|
188
|
-
sampleCnt = rf.channels * rf.frames;
|
|
189
|
-
}
|
|
190
|
-
// TODO use download storage type depending on sample count of file
|
|
191
|
-
if (rf && rf.samplerate && sampleCnt != null && sampleCnt > this._maxAutoNetMemStoreSamples) {
|
|
192
|
-
const baseUrl = this.recoFileUrl(recordingFileId);
|
|
193
|
-
const obNetAb = this.chunkAudioRequestToNetAudioBuffer(baseUrl, 0, rf?.samplerate, BasicRecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS, rf.frames);
|
|
194
|
-
obNetAb.subscribe({
|
|
195
|
-
next: (nab) => {
|
|
196
|
-
let adh = new AudioDataHolder(nab);
|
|
197
|
-
if (rf) {
|
|
198
|
-
RecordingFileUtils.setAudioData(rf, adh);
|
|
199
|
-
observer.next(rf);
|
|
200
|
-
}
|
|
201
|
-
},
|
|
202
|
-
complete: () => {
|
|
203
|
-
observer.complete();
|
|
204
|
-
},
|
|
205
|
-
error: (error) => {
|
|
206
|
-
if (error.status == 404) {
|
|
207
|
-
// Interpret not as an error, the file ist not recorded yet
|
|
208
|
-
observer.next(null);
|
|
209
|
-
observer.complete();
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
// all other states are errors
|
|
213
|
-
observer.error(error);
|
|
214
|
-
observer.complete();
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
let rfAudioObs = this.fetchAudiofile(recordingFileId);
|
|
221
|
-
rfAudioObs.subscribe({ next: resp => {
|
|
222
|
-
// Do not use Promise version, which does not work with Safari 13
|
|
223
|
-
if (resp.body) {
|
|
224
|
-
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
225
|
-
if (rf) {
|
|
226
|
-
let as = new AudioBufferSource(ab);
|
|
227
|
-
let adh = new AudioDataHolder(as);
|
|
228
|
-
RecordingFileUtils.setAudioData(rf, adh);
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
observer.error('Recording file object null');
|
|
232
|
-
}
|
|
233
|
-
if (this.debugDelay > 0) {
|
|
234
|
-
window.setTimeout(() => {
|
|
235
|
-
observer.next(rf);
|
|
236
|
-
observer.complete();
|
|
237
|
-
}, this.debugDelay);
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
observer.next(rf);
|
|
241
|
-
observer.complete();
|
|
242
|
-
}
|
|
243
|
-
}).catch(reason => { observer.error(reason); });
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
observer.error('Received no audio data');
|
|
247
|
-
}
|
|
248
|
-
},
|
|
249
|
-
error: (error) => {
|
|
250
|
-
if (error.status == 404) {
|
|
251
|
-
// Interpret not as an error, the file ist not recorded yet
|
|
252
|
-
observer.next(null);
|
|
253
|
-
observer.complete();
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
// all other states are errors
|
|
257
|
-
observer.error(error);
|
|
258
|
-
observer.complete();
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
return wobs;
|
|
267
|
-
}
|
|
268
|
-
saveEditSelection(recordingFileId, editSampleRate, editStartFrame, editEndFrame) {
|
|
269
|
-
let recUrl = this.apiEndPoint + RecordingFileService.RECOFILE_API_CTX + '/' + recordingFileId;
|
|
270
|
-
if (this.config && this.config.apiType === ApiType.FILES) {
|
|
271
|
-
// for development and demo
|
|
272
|
-
// append UUID to make request URL unique to avoid localhost server caching
|
|
273
|
-
recUrl = recUrl + '.json?requestUUID=' + UUID.generate();
|
|
274
|
-
}
|
|
275
|
-
//console.log("Path request URL: "+recUrl)
|
|
276
|
-
return this.http.patch(recUrl, { editSampleRate: editSampleRate, editStartFrame: editStartFrame, editEndFrame: editEndFrame }, { withCredentials: this.withCredentials });
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
RecordingFileService.RECOFILE_API_CTX = 'recordingfile';
|
|
280
|
-
RecordingFileService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingFileService, deps: [{ token: i1.HttpClient }, { token: SPEECHRECORDER_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
281
|
-
RecordingFileService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingFileService });
|
|
282
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingFileService, decorators: [{
|
|
283
|
-
type: Injectable
|
|
284
|
-
}], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: i2.SpeechRecorderConfig, decorators: [{
|
|
285
|
-
type: Inject,
|
|
286
|
-
args: [SPEECHRECORDER_CONFIG]
|
|
287
|
-
}] }]; } });
|
|
288
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3JkaW5nZmlsZS1zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc3BlZWNocmVjb3JkZXJuZy9zcmMvbGliL3NwZWVjaHJlY29yZGVyL3Nlc3Npb24vcmVjb3JkaW5nZmlsZS9yZWNvcmRpbmdmaWxlLXNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDakQsT0FBTyxFQUFnQyxXQUFXLEVBQWUsTUFBTSxzQkFBc0IsQ0FBQztBQUc5RixPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBR2hDLE9BQU8sRUFBQyxPQUFPLEVBQUUscUJBQXFCLEVBQXVCLE1BQU0scUJBQXFCLENBQUM7QUFDekYsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQzFDLE9BQU8sRUFBZ0Isa0JBQWtCLEVBQW1CLE1BQU0saUJBQWlCLENBQUM7QUFDcEYsT0FBTyxFQUFDLGlCQUFpQixFQUFFLGVBQWUsRUFBQyxNQUFNLGtDQUFrQyxDQUFDO0FBQ3BGLE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLDBDQUEwQyxDQUFDO0FBQy9FLE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLHdCQUF3QixDQUFDOzs7O0FBSTVELE1BQU0sT0FBTyxvQkFBcUIsU0FBUSxxQkFBcUI7SUFPN0QsWUFBc0IsSUFBZ0IsRUFBMkMsTUFBNkI7UUFDMUcsS0FBSyxDQUFDLElBQUksRUFBQyxNQUFNLENBQUMsQ0FBQztRQURELFNBQUksR0FBSixJQUFJLENBQVk7UUFBMkMsV0FBTSxHQUFOLE1BQU0sQ0FBdUI7UUFIOUcsa0NBQWtDO1FBQzFCLGVBQVUsR0FBUSxDQUFDLENBQUM7SUFJNUIsQ0FBQztJQUVPLFdBQVcsQ0FBQyxlQUFnQztRQUNsRCxJQUFJLFlBQVksR0FBQyxrQkFB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ZW50IjpbImltcG9ydCB7SW5qZWN0LCBJbmplY3RhYmxlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtIdHRwQ2xpZW50LCBIdHRwRXJyb3JSZXNwb25zZSwgSHR0cEhlYWRlcnMsIEh0dHBSZXNwb25zZX0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vbi9odHRwXCI7XHJcblxyXG5cclxuaW1wb3J0IHtPYnNlcnZhYmxlfSBmcm9tIFwicnhqc1wiO1xyXG5cclxuXHJcbmltcG9ydCB7QXBpVHlwZSwgU1BFRUNIUkVDT1JERVJfQ09ORklHLCBTcGVlY2hSZWNvcmRlckNvbmZpZ30gZnJvbSBcIi4uLy4uLy4uL3Nwci5jb25maWdcIjtcclxuaW1wb3J0IHtVVUlEfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvdXRpbHNcIjtcclxuaW1wb3J0IHtSZWNvcmRpbmdGaWxlLCBSZWNvcmRpbmdGaWxlVXRpbHMsIFNwclJlY29yZGluZ0ZpbGV9IGZyb20gXCIuLi8uLi9yZWNvcmRpbmdcIjtcclxuaW1wb3J0IHtBdWRpb0J1ZmZlclNvdXJjZSwgQXVkaW9EYXRhSG9sZGVyfSBmcm9tIFwiLi4vLi4vLi4vYXVkaW8vYXVkaW9fZGF0YV9ob2xkZXJcIjtcclxuaW1wb3J0IHtCYXNpY1JlY29yZGluZ1NlcnZpY2V9IGZyb20gXCIuLi8uLi9yZWNvcmRpbmdzL2Jhc2ljX3JlY29yZGluZy5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7QXVkaW9Db250ZXh0UHJvdmlkZXJ9IGZyb20gXCIuLi8uLi8uLi9hdWRpby9jb250ZXh0XCI7XHJcblxyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRmlsZVNlcnZpY2UgZXh0ZW5kcyBCYXNpY1JlY29yZGluZ1NlcnZpY2V7XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUkVDT0ZJTEVfQVBJX0NUWCA9ICdyZWNvcmRpbmdmaWxlJ1xyXG5cclxuICAvL3ByaXZhdGUgZGVidWdEZWxheTpudW1iZXI9MTAwMDA7XHJcbiAgcHJpdmF0ZSBkZWJ1Z0RlbGF5Om51bWJlcj0wO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgaHR0cDogSHR0cENsaWVudCwgQEluamVjdChTUEVFQ0hSRUNPUkRFUl9DT05GSUcpIHByb3RlY3RlZCBjb25maWc/OiBTcGVlY2hSZWNvcmRlckNvbmZpZykge1xyXG4gICAgICBzdXBlcihodHRwLGNvbmZpZyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlY29GaWxlVXJsKHJlY29yZGluZ0ZpbGVJZDogc3RyaW5nIHwgbnVtYmVyKTpzdHJpbmd7XHJcbiAgICBsZXQgZW5jUmVjZmlsZUlkPWVuY29kZVVSSUNvbXBvbmVudChyZWNvcmRpbmdGaWxlSWQpO1xyXG4gICAgbGV0IHJlY1VybCA9IHRoaXMuYXBpRW5kUG9pbnQgKyBSZWNvcmRpbmdGaWxlU2VydmljZS5SRUNPRklMRV9BUElfQ1RYICsgJy8nICsgZW5jUmVjZmlsZUlkO1xyXG5cclxuICAgIHJldHVybiByZWNVcmw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZldGNoQXVkaW9maWxlKHJlY29yZGluZ0ZpbGVJZDogc3RyaW5nIHwgbnVtYmVyKTogT2JzZXJ2YWJsZTxIdHRwUmVzcG9uc2U8QXJyYXlCdWZmZXI+PiB7XHJcbiAgICBsZXQgcmVjVXJsID0gdGhpcy5yZWNvRmlsZVVybChyZWNvcmRpbmdGaWxlSWQpO1xyXG4gICAgaWYgKHRoaXMuY29uZmlnICYmIHRoaXMuY29uZmlnLmFwaVR5cGUgPT09IEFwaVR5cGUuRklMRVMpIHtcclxuICAgICAgLy8gZm9yIGRldmVsb3BtZW50IGFuZCBkZW1vXHJcbiAgICAgIC8vIGFwcGVuZCBVVUlEIHRvIG1ha2UgcmVxdWVzdCBVUkwgdW5pcXVlIHRvIGF2b2lkIGxvY2FsaG9zdCBzZXJ2ZXIgY2FjaGluZ1xyXG4gICAgICByZWNVcmwgPSByZWNVcmwgKyAnLndhdic7XHJcbiAgICB9XHJcbiAgICBsZXQgaGVhZGVycyA9IG5ldyBIdHRwSGVhZGVycyh7XHJcbiAgICAgICdBY2NlcHQnOiAnYXVkaW8vd2F2J1xyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQocmVjVXJsLCB7XHJcbiAgICAgIG9ic2VydmU6ICdyZXNwb25zZScsXHJcbiAgICAgIGhlYWRlcnM6IGhlYWRlcnMsXHJcbiAgICAgIHJlc3BvbnNlVHlwZTogJ2FycmF5YnVmZmVyJyxcclxuICAgICAgd2l0aENyZWRlbnRpYWxzOiB0aGlzLndpdGhDcmVkZW50aWFsc1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlY29yZGluZ0ZpbGVEZXNjck9ic2VydmVyKHJlY29yZGluZ0ZpbGVJZDogc3RyaW5nIHwgbnVtYmVyKTogT2JzZXJ2YWJsZTxSZWNvcmRpbmdGaWxlPiB7XHJcblxyXG4gICAgbGV0IHJlY1VybCA9IHRoaXMucmVjb0ZpbGVVcmwocmVjb3JkaW5nRmlsZUlkKTtcclxuICAgIGlmICh0aGlzLmNvbmZpZyAmJiB0aGlzLmNvbmZpZy5hcGlUeXBlID09PSBBcGlUeXBlLkZJTEVTKSB7XHJcbiAgICAgIC8vIGZvciBkZXZlbG9wbWVudCBhbmQgZGVtb1xyXG4gICAgICAvLyBhcHBlbmQgVVVJRCB0byBtYWtlIHJlcXVlc3QgVVJMIHVuaXF1ZSB0byBhdm9pZCBsb2NhbGhvc3Qgc2VydmVyIGNhY2hpbmdcclxuICAgICAgcmVjVXJsID0gcmVjVXJsICsgJy5qc29uP3JlcXVlc3RVVUlEPScrVVVJRC5nZW5lcmF0ZSgpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8UmVjb3JkaW5nRmlsZT4ocmVjVXJsLHsgd2l0aENyZWRlbnRpYWxzOiB0aGlzLndpdGhDcmVkZW50aWFscyB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc3ByUmVjb3JkaW5nRmlsZURlc2NyT2JzZXJ2ZXIocmVjb3JkaW5nRmlsZUlkOiBzdHJpbmcgfCBudW1iZXIpOiBPYnNlcnZhYmxlPFNwclJlY29yZGluZ0ZpbGU+IHtcclxuXHJcbiAgICBsZXQgcmVjVXJsID0gdGhpcy5yZWNvRmlsZVVybChyZWNvcmRpbmdGaWxlSWQpO1xyXG4gICAgaWYgKHRoaXMuY29uZmlnICYmIHRoaXMuY29uZmlnLmFwaVR5cGUgPT09IEFwaVR5cGUuRklMRVMpIHtcclxuICAgICAgLy8gZm9yIGRldmVsb3BtZW50IGFuZCBkZW1vXHJcbiAgICAgIC8vIGFwcGVuZCBVVUlEIHRvIG1ha2UgcmVxdWVzdCBVUkwgdW5pcXVlIHRvIGF2b2lkIGxvY2FsaG9zdCBzZXJ2ZXIgY2FjaGluZ1xyXG4gICAgICByZWNVcmwgPSByZWNVcmwgKyAnLmpzb24/cmVxdWVzdFVVSUQ9JytVVUlELmdlbmVyYXRlKCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy5odHRwLmdldDxTcHJSZWNvcmRpbmdGaWxlPihyZWNVcmwseyB3aXRoQ3JlZGVudGlhbHM6IHRoaXMud2l0aENyZWRlbnRpYWxzIH0pO1xyXG4gIH1cclxuXHJcblxyXG4gIHByaXZhdGUgZmV0Y2hTZXNzaW9uQXVkaW9maWxlQnlJZChwcm9qZWN0TmFtZTogc3RyaW5nLCBzZXNzSWQ6IHN0cmluZyB8IG51bWJlciwgcmVjb3JkaW5nRmlsZUlkOiBzdHJpbmcgfCBudW1iZXIpOiBPYnNlcnZhYmxlPEh0dHBSZXNwb25zZTxBcnJheUJ1ZmZlcj4+IHtcclxuXHJcbiAgICBsZXQgcmVjVXJsID0gdGhpcy5yZWNvRmlsZVVybChyZWNvcmRpbmdGaWxlSWQpO1xyXG4gICAgLy8gaWYgKHRoaXMuY29uZmlnICYmIHRoaXMuY29uZmlnLmFwaVR5cGUgPT09IEFwaVR5cGUuRklMRVMpIHtcclxuICAgIC8vICAgLy8gZm9yIGRldmVsb3BtZW50IGFuZCBkZW1vXHJcbiAgICAvLyAgIC8vIGFwcGVuZCBVVUlEIHRvIG1ha2UgcmVxdWVzdCBVUkwgdW5pcXVlIHRvIGF2b2lkIGxvY2FsaG9zdCBzZXJ2ZXIgY2FjaGluZ1xyXG4gICAgLy8gICByZWNVcmwgPSByZWNVcmwgKyAnLndhdj9yZXF1ZXN0VVVJRD0nICsgVVVJRC5nZW5lcmF0ZSgpO1xyXG4gICAgLy8gfVxyXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQocmVjVXJsLCB7XHJcbiAgICAgIG9ic2VydmU6ICdyZXNwb25zZScsXHJcbiAgICAgIHJlc3BvbnNlVHlwZTogJ2FycmF5YnVmZmVyJyxcclxuICAgICAgd2l0aENyZWRlbnRpYWxzOiB0aGlzLndpdGhDcmVkZW50aWFsc1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuXHJcbiAgLy8gVE9ETyB0ZXN0XHJcblxyXG4gIGZldGNoQW5kQXBwbHlSZWNvcmRpbmdGaWxlKHJlY29yZGluZ0ZpbGU6U3ByUmVjb3JkaW5nRmlsZSk6T2JzZXJ2YWJsZTxTcHJSZWNvcmRpbmdGaWxlfG51bGw+IHtcclxuXHJcbiAgICBsZXQgd29icyA9IG5ldyBPYnNlcnZhYmxlPFNwclJlY29yZGluZ0ZpbGV8bnVsbD4ob2JzZXJ2ZXI9PntcclxuICAgICAgaWYocmVjb3JkaW5nRmlsZS5yZWNvcmRpbmdGaWxlSWQpIHtcclxuICAgICAgICBsZXQgb2JzID0gdGhpcy5mZXRjaEF1ZGlvZmlsZShyZWNvcmRpbmdGaWxlLnJlY29yZGluZ0ZpbGVJZCk7XHJcblxyXG4gICAgICAgIG9icy5zdWJzY3JpYmUoXHJcbiAgICAgICAgICAgIHtuZXh0OnJlc3AgPT4ge1xyXG4gICAgICAgICAgICAgIGlmKHJlc3AuYm9keSkge1xyXG4gICAgICAgICAgICAgICAgQXVkaW9Db250ZXh0UHJvdmlkZXIuZGVjb2RlQXVkaW9EYXRhKHJlc3AuYm9keSkudGhlbihhYiA9PiB7XHJcbiAgICAgICAgICAgICAgICAgIGxldCBhcz1uZXcgQXVkaW9CdWZmZXJTb3VyY2UoYWIpO1xyXG4gICAgICAgICAgICAgICAgICBSZWNvcmRpbmdGaWxlVXRpbHMuc2V0QXVkaW9EYXRhKHJlY29yZGluZ0ZpbGUsbmV3IEF1ZGlvRGF0YUhvbGRlcihhcykpO1xyXG4gICAgICAgICAgICAgICAgICBpZiAodGhpcy5kZWJ1Z0RlbGF5ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHJlY29yZGluZ0ZpbGUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcclxuICAgICAgICAgICAgICAgICAgICB9LCB0aGlzLmRlYnVnRGVsYXkpO1xyXG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQocmVjb3JkaW5nRmlsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSkuY2F0Y2gocmVhc29uPT57b2JzZXJ2ZXIuZXJyb3IocmVhc29uKX0pO1xyXG4gICAgICAgICAgICAgIH1lbHNle1xyXG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoJ1JlY2VpdmVkIG5vIGF1ZGlvIGRhdGEhJyk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBlcnJvcjooZXJyb3I6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XHJcbiAgICAgICAgICAgICAgaWYgKGVycm9yLnN0YXR1cyA9PSA0MDQpIHtcclxuICAgICAgICAgICAgICAgIC8vIEludGVycHJldCBub3QgYXMgYW4gZXJyb3IsIHRoZSBmaWxlIGlzdCBub3QgcmVjb3JkZWQgeWV0XHJcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KG51bGwpO1xyXG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKVxyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyBhbGwgb3RoZXIgc3RhdGVzIGFyZSBlcnJvcnNcclxuICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcclxuICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgICB9ZWxzZXtcclxuICAgICAgICBvYnNlcnZlci5lcnJvcigpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gd29icztcclxuICB9XHJcblxyXG4gIGZldGNoUmVjb3JkaW5nRmlsZShhQ3R4OiBBdWRpb0NvbnRleHQsIHJlY29yZGluZ0ZpbGVJZDogc3RyaW5nIHwgbnVtYmVyKTogT2JzZXJ2YWJsZTxSZWNvcmRpbmdGaWxlIHwgbnVsbD4ge1xyXG5cclxuICAgIGxldCB3b2JzID0gbmV3IE9ic2VydmFibGU8UmVjb3JkaW5nRmlsZSB8IG51bGw+KG9ic2VydmVyID0+IHtcclxuICAgICAgbGV0IHJmOiBSZWNvcmRpbmdGaWxlfG51bGwgPSBudWxsO1xyXG4gICAgICBsZXQgcmZEZXNjck9icyA9IHRoaXMucmVjb3JkaW5nRmlsZURlc2NyT2JzZXJ2ZXIocmVjb3JkaW5nRmlsZUlkKTtcclxuICAgICAgcmZEZXNjck9icy5zdWJzY3JpYmUoXHJcbiAgICAgICAgICB7bmV4dDp2YWx1ZSA9PiB7XHJcbiAgICAgICAgcmYgPSB2YWx1ZTtcclxuICAgICAgfSwgZXJyb3I6KGVycm9yKSA9PiB7XHJcbiAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xyXG4gICAgICB9LCBjb21wbGV0ZTooKSA9PiB7XHJcbiAgICAgICAgbGV0IHJmQXVkaW9PYnMgPSB0aGlzLmZldGNoQXVkaW9maWxlKHJlY29yZGluZ0ZpbGVJZCk7XHJcbiAgICAgICAgcmZBdWRpb09icy5zdWJzY3JpYmUoe1xyXG4gICAgICAgICAgbmV4dDogcmVzcCA9PiB7XHJcbiAgICAgICAgICAgIC8vIERvIG5vdCB1c2UgUHJvbWlzZSB2ZXJzaW9uLCB3aGljaCBkb2VzIG5vdCB3b3JrIHdpdGggU2FmYXJpIDEzXHJcbiAgICAgICAgICAgIGlmIChyZXNwLmJvZHkpIHtcclxuICAgICAgICAgICAgICBBdWRpb0NvbnRleHRQcm92aWRlci5kZWNvZGVBdWRpb0RhdGEocmVzcC5ib2R5KS50aGVuKCBhYiA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAocmYpIHtcclxuICAgICAgICAgICAgICAgICAgbGV0IGFzID0gbmV3IEF1ZGlvQnVmZmVyU291cmNlKGFiKTtcclxuICAgICAgICAgICAgICAgICAgUmVjb3JkaW5nRmlsZVV0aWxzLnNldEF1ZGlvRGF0YShyZiwgbmV3IEF1ZGlvRGF0YUhvbGRlcihhcykpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoJ1JlY29yZGluZyBmaWxlIG9iamVjdCBudWxsJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kZWJ1Z0RlbGF5ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChyZik7XHJcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcclxuICAgICAgICAgICAgICAgICAgfSwgdGhpcy5kZWJ1Z0RlbGF5KTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQocmYpO1xyXG4gICAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH0pLmNhdGNoKHJlYXNvbiA9PiB7b2JzZXJ2ZXIuZXJyb3IocmVhc29uKX0pO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKCdSZWNlaXZlZCBubyBhdWRpbyBkYXRhJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgICBlcnJvcjogKGVycm9yOiBIdHRwRXJyb3JSZXNwb25zZSkgPT4ge1xyXG4gICAgICAgICAgICBpZiAoZXJyb3Iuc3RhdHVzID09IDQwNCkge1xyXG4gICAgICAgICAgICAgIC8vIEludGVycHJldCBub3QgYXMgYW4gZXJyb3IsIHRoZSBmaWxlIGlzdCBub3QgcmVjb3JkZWQgeWV0XHJcbiAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChudWxsKTtcclxuICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpXHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgLy8gYWxsIG90aGVyIHN0YXRlcyBhcmUgZXJyb3JzXHJcbiAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xyXG4gICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHdvYnM7XHJcbiAgfVxyXG5cclxuICBmZXRjaFNwclJlY29yZGluZ0ZpbGUoIHJlY29yZGluZ0ZpbGVJZDogc3RyaW5nIHwgbnVtYmVyKTogT2JzZXJ2YWJsZTxTcHJSZWNvcmRpbmdGaWxlIHwgbnVsbD4ge1xyXG5cclxuICAgIGxldCB3b2JzID0gbmV3IE9ic2VydmFibGU8U3ByUmVjb3JkaW5nRmlsZSB8IG51bGw+KG9ic2VydmVyID0+IHtcclxuICAgICAgbGV0IHJmOiBTcHJSZWNvcmRpbmdGaWxlfG51bGwgPSBudWxsO1xyXG4gICAgICBsZXQgcmZEZXNjck9icyA9IHRoaXMuc3ByUmVjb3JkaW5nRmlsZURlc2NyT2JzZXJ2ZXIocmVjb3JkaW5nRmlsZUlkKTtcclxuICAgICAgcmZEZXNjck9icy5zdWJzY3JpYmUoe25leHQ6dmFsdWUgPT4ge1xyXG4gICAgICAgIHJmID0gdmFsdWU7XHJcbiAgICAgIH1cclxuICAgICwgZXJyb3I6KGVycm9yKSA9PiB7XHJcbiAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xyXG4gICAgICB9LCBjb21wbGV0ZTooKSA9PiB7XHJcbiAgICAgICAgbGV0IHNhbXBsZUNudDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XHJcbiAgICAgICAgaWYgKHJmICYmIHJmLmNoYW5uZWxzICYmIHJmLmZyYW1lcykge1xyXG4gICAgICAgICAgc2FtcGxlQ250ID0gcmYuY2hhbm5lbHMgKiByZi5mcmFtZXM7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIFRPRE8gdXNlIGRvd25sb2FkIHN0b3JhZ2UgdHlwZSBkZXBlbmRpbmcgb24gc2FtcGxlIGNvdW50IG9mIGZpbGVcclxuICAgICAgICBpZiAocmYgJiYgcmYuc2FtcGxlcmF0ZSAmJiBzYW1wbGVDbnQgIT0gbnVsbCAmJiBzYW1wbGVDbnQgPiB0aGlzLl9tYXhBdXRvTmV0TWVtU3RvcmVTYW1wbGVzKSB7XHJcbiAgICAgICAgICBjb25zdCBiYXNlVXJsID0gdGhpcy5yZWNvRmlsZVVybChyZWNvcmRpbmdGaWxlSWQpO1xyXG4gICAgICAgICAgY29uc3Qgb2JOZXRBYiA9IHRoaXMuY2h1bmtBdWRpb1JlcXVlc3RUb05ldEF1ZGlvQnVmZmVyKGJhc2VVcmwsIDAsIHJmPy5zYW1wbGVyYXRlLCBCYXNpY1JlY29yZGluZ1NlcnZpY2UuREVGQVVMVF9DSFVOS0VEX0RPV05MT0FEX1NFQ09ORFMsIHJmLmZyYW1lcyk7XHJcbiAgICAgICAgICBvYk5ldEFiLnN1YnNjcmliZShcclxuICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBuZXh0OiAobmFiKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgIGxldCBhZGggPSBuZXcgQXVkaW9EYXRhSG9sZGVyKG5hYik7XHJcbiAgICAgICAgICAgICAgICAgIGlmIChyZikge1xyXG4gICAgICAgICAgICAgICAgICAgIFJlY29yZGluZ0ZpbGVVdGlscy5zZXRBdWRpb0RhdGEocmYsIGFkaCk7XHJcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChyZik7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICBjb21wbGV0ZTogKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcclxuICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLnN0YXR1cyA9PSA0MDQpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBJbnRlcnByZXQgbm90IGFzIGFuIGVycm9yLCB0aGUgZmlsZSBpc3Qgbm90IHJlY29yZGVkIHlldFxyXG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQobnVsbCk7XHJcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKVxyXG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGFsbCBvdGhlciBzdGF0ZXMgYXJlIGVycm9yc1xyXG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG5cclxuICAgICAgICAgIGxldCByZkF1ZGlvT2JzID0gdGhpcy5mZXRjaEF1ZGlvZmlsZShyZWNvcmRpbmdGaWxlSWQpO1xyXG4gICAgICAgICAgcmZBdWRpb09icy5zdWJzY3JpYmUoXHJcbiAgICAgICAgICAgICAge25leHQ6cmVzcCA9PlxyXG4gICAgICAgICAge1xyXG4gICAgICAgICAgICAvLyBEbyBub3QgdXNlIFByb21pc2UgdmVyc2lvbiwgd2hpY2ggZG9lcyBub3Qgd29yayB3aXRoIFNhZmFyaSAxM1xyXG4gICAgICAgICAgICBpZiAocmVzcC5ib2R5KSB7XHJcbiAgICAgICAgICAgICAgQXVkaW9Db250ZXh0UHJvdmlkZXIuZGVjb2RlQXVkaW9EYXRhKHJlc3AuYm9keSkudGhlbiggYWIgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKHJmKSB7XHJcbiAgICAgICAgICAgICAgICAgIGxldCBhcyA9IG5ldyBBdWRpb0J1ZmZlclNvdXJjZShhYik7XHJcbiAgICAgICAgICAgICAgICAgIGxldCBhZGggPSBuZXcgQXVkaW9EYXRhSG9sZGVyKGFzKTtcclxuICAgICAgICAgICAgICAgICAgUmVjb3JkaW5nRmlsZVV0aWxzLnNldEF1ZGlvRGF0YShyZiwgYWRoKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKCdSZWNvcmRpbmcgZmlsZSBvYmplY3QgbnVsbCcpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZGVidWdEZWxheSA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQocmYpO1xyXG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgICAgICAgICAgIH0sIHRoaXMuZGVidWdEZWxheSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHJmKTtcclxuICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9KS5jYXRjaChyZWFzb24gPT4ge29ic2VydmVyLmVycm9yKHJlYXNvbil9KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcignUmVjZWl2ZWQgbm8gYXVkaW8gZGF0YScpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgLCBlcnJvcjooZXJyb3I6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChlcnJvci5zdGF0dXMgPT0gNDA0KSB7XHJcbiAgICAgICAgICAgICAgLy8gSW50ZXJwcmV0IG5vdCBhcyBhbiBlcnJvciwgdGhlIGZpbGUgaXN0IG5vdCByZWNvcmRlZCB5ZXRcclxuICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KG51bGwpO1xyXG4gICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKClcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAvLyBhbGwgb3RoZXIgc3RhdGVzIGFyZSBlcnJvcnNcclxuICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcihlcnJvcik7XHJcbiAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gd29icztcclxuICB9XHJcblxyXG4gIHNhdmVFZGl0U2VsZWN0aW9uKHJlY29yZGluZ0ZpbGVJZDogc3RyaW5nIHwgbnVtYmVyLGVkaXRTYW1wbGVSYXRlOm51bWJlcnxudWxsLGVkaXRTdGFydEZyYW1lOm51bWJlcnxudWxsLGVkaXRFbmRGcmFtZTpudW1iZXJ8bnVsbCk6IE9ic2VydmFibGU8U3ByUmVjb3JkaW5nRmlsZSB8IG51bGw+IHtcclxuICAgIGxldCByZWNVcmwgPSB0aGlzLmFwaUVuZFBvaW50ICsgUmVjb3JkaW5nRmlsZVNlcnZpY2UuUkVDT0ZJTEVfQVBJX0NUWCArICcvJyArIHJlY29yZGluZ0ZpbGVJZDtcclxuICAgIGlmICh0aGlzLmNvbmZpZyAmJiB0aGlzLmNvbmZpZy5hcGlUeXBlID09PSBBcGlUeXBlLkZJTEVTKSB7XHJcbiAgICAgIC8vIGZvciBkZXZlbG9wbWVudCBhbmQgZGVtb1xyXG4gICAgICAvLyBhcHBlbmQgVVVJRCB0byBtYWtlIHJlcXVlc3QgVVJMIHVuaXF1ZSB0byBhdm9pZCBsb2NhbGhvc3Qgc2VydmVyIGNhY2hpbmdcclxuICAgICAgcmVjVXJsID0gcmVjVXJsICsgJy5qc29uP3JlcXVlc3RVVUlEPScrVVVJRC5nZW5lcmF0ZSgpO1xyXG4gICAgfVxyXG4gICAgLy9jb25zb2xlLmxvZyhcIlBhdGggcmVxdWVzdCBVUkw6IFwiK3JlY1VybClcclxuICAgIHJldHVybiB0aGlzLmh0dHAucGF0Y2g8U3ByUmVjb3JkaW5nRmlsZT4ocmVjVXJsLHtlZGl0U2FtcGxlUmF0ZTplZGl0U2FtcGxlUmF0ZSxlZGl0U3RhcnRGcmFtZTplZGl0U3RhcnRGcmFtZSxlZGl0RW5kRnJhbWU6ZWRpdEVuZEZyYW1lfSx7IHdpdGhDcmVkZW50aWFsczogdGhpcy53aXRoQ3JlZGVudGlhbHMgfSk7XHJcbiAgfVxyXG5cclxufVxyXG5cclxuXHJcbiJdfQ==
|