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
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Created by klausj on 17.06.2017.
|
|
3
|
+
*/
|
|
4
|
+
import { Inject, Injectable } from '@angular/core';
|
|
5
|
+
import { ApiType, SPEECHRECORDER_CONFIG } from "../../spr.config";
|
|
6
|
+
import { UUID } from "../../utils/utils";
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
import * as i1 from "@angular/common/http";
|
|
9
|
+
import * as i2 from "@angular/common";
|
|
10
|
+
import * as i3 from "../../spr.config";
|
|
11
|
+
export class ProjectService {
|
|
12
|
+
static { this.PROJECT_API_CTX = 'project'; }
|
|
13
|
+
constructor(http, platformLocation, config) {
|
|
14
|
+
this.http = http;
|
|
15
|
+
this.platformLocation = platformLocation;
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.withCredentials = false;
|
|
18
|
+
console.log("Base Href: " + platformLocation.getBaseHrefFromDOM());
|
|
19
|
+
let apiEndPoint = '';
|
|
20
|
+
if (config && config.apiEndPoint) {
|
|
21
|
+
apiEndPoint = config.apiEndPoint;
|
|
22
|
+
}
|
|
23
|
+
if (apiEndPoint !== '') {
|
|
24
|
+
apiEndPoint = apiEndPoint + '/';
|
|
25
|
+
}
|
|
26
|
+
if (config != null && config.withCredentials != null) {
|
|
27
|
+
this.withCredentials = config.withCredentials;
|
|
28
|
+
}
|
|
29
|
+
this.projectCtxUrl = apiEndPoint + ProjectService.PROJECT_API_CTX;
|
|
30
|
+
}
|
|
31
|
+
appendRequestUUIDForDevelopmentServer(url) {
|
|
32
|
+
let resUrl = url;
|
|
33
|
+
if (this.config && this.config.apiType === ApiType.FILES) {
|
|
34
|
+
// for development and demo
|
|
35
|
+
// append UUID to make request URL unique to avoid localhost server caching
|
|
36
|
+
resUrl = resUrl + '.json?requestUUID=' + UUID.generate();
|
|
37
|
+
}
|
|
38
|
+
return resUrl;
|
|
39
|
+
}
|
|
40
|
+
projectUrl(id) {
|
|
41
|
+
let encPrjId = encodeURIComponent(id);
|
|
42
|
+
return this.appendRequestUUIDForDevelopmentServer(this.projectCtxUrl + '/' + encPrjId);
|
|
43
|
+
}
|
|
44
|
+
projectResourceUrl(projectId, relResourcePath) {
|
|
45
|
+
let encPrjId = encodeURIComponent(projectId);
|
|
46
|
+
// Use encodeURI here since the relatice resource path from recording scripts is already a URI
|
|
47
|
+
// encodeURIComponent function would encode the slashes and fetching the resource would fail
|
|
48
|
+
let encRelResPath = encodeURI(relResourcePath);
|
|
49
|
+
return this.projectCtxUrl + '/' + encPrjId + '/' + encRelResPath;
|
|
50
|
+
}
|
|
51
|
+
projectObservable(id) {
|
|
52
|
+
let prjUrl = this.projectUrl(id);
|
|
53
|
+
return this.http.get(prjUrl, { withCredentials: this.withCredentials });
|
|
54
|
+
}
|
|
55
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.6", ngImport: i0, type: ProjectService, deps: [{ token: i1.HttpClient }, { token: i2.PlatformLocation }, { token: SPEECHRECORDER_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
56
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.6", ngImport: i0, type: ProjectService }); }
|
|
57
|
+
}
|
|
58
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.6", ngImport: i0, type: ProjectService, decorators: [{
|
|
59
|
+
type: Injectable
|
|
60
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.PlatformLocation }, { type: i3.SpeechRecorderConfig, decorators: [{
|
|
61
|
+
type: Inject,
|
|
62
|
+
args: [SPEECHRECORDER_CONFIG]
|
|
63
|
+
}] }] });
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvamVjdC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc3BlZWNocmVjb3JkZXJuZy9zcmMvbGliL3NwZWVjaHJlY29yZGVyL3Byb2plY3QvcHJvamVjdC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsT0FBTyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFFakQsT0FBTyxFQUFDLE9BQU8sRUFBRSxxQkFBcUIsRUFBdUIsTUFBTSxrQkFBa0IsQ0FBQztBQUV0RixPQUFPLEVBQUMsSUFBSSxFQUFDLE1BQU0sbUJBQW1CLENBQUM7Ozs7O0FBT3ZDLE1BQU0sT0FBTyxjQUFjO2FBQ0Ysb0JBQWUsR0FBQyxTQUFTLEFBQVYsQ0FBVTtJQUloRCxZQUFvQixJQUFlLEVBQVMsZ0JBQWlDLEVBQXdDLE1BQTRCO1FBQTdILFNBQUksR0FBSixJQUFJLENBQVc7UUFBUyxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWlCO1FBQXdDLFdBQU0sR0FBTixNQUFNLENBQXNCO1FBRmhJLG9CQUFlLEdBQVMsS0FBSyxDQUFDO1FBSTdDLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxHQUFDLGdCQUFnQixDQUFDLGtCQUFrQixFQUFFLENBQUMsQ0FBQztRQUVqRSxJQUFJLFdBQVcsR0FBRyxFQUFFLENBQUE7UUFFcEIsSUFBRyxNQUFNLElBQUksTUFBTSxDQUFDLFdBQVcsRUFBRTtZQUMvQixXQUFXLEdBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQztTQUNoQztRQUNELElBQUcsV0FBVyxLQUFLLEVBQUUsRUFBQztZQUNwQixXQUFXLEdBQUMsV0FBVyxHQUFDLEdBQUcsQ0FBQTtTQUM1QjtRQUNELElBQUcsTUFBTSxJQUFFLElBQUksSUFBSSxNQUFNLENBQUMsZUFBZSxJQUFFLElBQUksRUFBQztZQUM5QyxJQUFJLENBQUMsZUFBZSxHQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUM7U0FDN0M7UUFFRCxJQUFJLENBQUMsYUFBYSxHQUFHLFdBQVcsR0FBRyxjQUFjLENBQUMsZUFBZSxDQUFDO0lBRXBFLENBQUM7SUFFTyxxQ0FBcUMsQ0FBQyxHQUFVO1FBQ3RELElBQUksTUFBTSxHQUFDLEdBQUcsQ0FBQztRQUNmLElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sS0FBSyxPQUFPLENBQUMsS0FBSyxFQUFFO1lBQ3hELDJCQUEyQjtZQUMzQiwyRUFBMkU7WUFDM0UsTUFBTSxHQUFHLE1BQU0sR0FBRyxvQkFBb0IsR0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDeEQ7UUFDRCxPQUFPLE1BQU0sQ0FBQTtJQUNmLENBQUM7SUFFRCxVQUFVLENBQUMsRUFBUztRQUNsQixJQUFJLFFBQVEsR0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNwQyxPQUFPLElBQUksQ0FBQyxxQ0FBcUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxHQUFHLEdBQUcsR0FBRyxRQUFRLENBQUMsQ0FBQztJQUN6RixDQUFDO0lBRUQsa0JBQWtCLENBQUMsU0FBaUIsRUFBQyxlQUFzQjtRQUN6RCxJQUFJLFFBQVEsR0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMzQyw4RkFBOEY7UUFDOUYsNEZBQTRGO1FBQzVGLElBQUksYUFBYSxHQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUM3QyxPQUFPLElBQUksQ0FBQyxhQUFhLEdBQUcsR0FBRyxHQUFHLFFBQVEsR0FBRSxHQUFHLEdBQUMsYUFBYSxDQUFDO0lBQ2hFLENBQUM7SUFFRCxpQkFBaUIsQ0FBQyxFQUFTO1FBQ3pCLElBQUksTUFBTSxHQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDOUIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBVSxNQUFNLEVBQUMsRUFBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLGVBQWUsRUFBQyxDQUFDLENBQUE7SUFDL0UsQ0FBQzs4R0FuRFMsY0FBYyw0RUFLNkQscUJBQXFCO2tIQUxoRyxjQUFjOzsyRkFBZCxjQUFjO2tCQUQxQixVQUFVOzswQkFNc0UsTUFBTTsyQkFBQyxxQkFBcUIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcclxuICogQ3JlYXRlZCBieSBrbGF1c2ogb24gMTcuMDYuMjAxNy5cclxuICovXHJcbmltcG9ydCB7SW5qZWN0LCBJbmplY3RhYmxlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtIdHRwQ2xpZW50fSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uL2h0dHBcIjtcclxuaW1wb3J0IHtBcGlUeXBlLCBTUEVFQ0hSRUNPUkRFUl9DT05GSUcsIFNwZWVjaFJlY29yZGVyQ29uZmlnfSBmcm9tIFwiLi4vLi4vc3ByLmNvbmZpZ1wiO1xyXG5pbXBvcnQge1Byb2plY3R9IGZyb20gXCIuL3Byb2plY3RcIjtcclxuaW1wb3J0IHtVVUlEfSBmcm9tIFwiLi4vLi4vdXRpbHMvdXRpbHNcIjtcclxuaW1wb3J0IHtPYnNlcnZhYmxlfSBmcm9tIFwicnhqc1wiO1xyXG5pbXBvcnQge1BsYXRmb3JtTG9jYXRpb259IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcclxuXHJcblxyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgUHJvamVjdFNlcnZpY2Uge1xyXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUFJPSkVDVF9BUElfQ1RYPSdwcm9qZWN0J1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvamVjdEN0eFVybDpzdHJpbmc7XHJcbiAgcHJpdmF0ZSByZWFkb25seSB3aXRoQ3JlZGVudGlhbHM6Ym9vbGVhbj1mYWxzZTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBodHRwOkh0dHBDbGllbnQscHJpdmF0ZSBwbGF0Zm9ybUxvY2F0aW9uOlBsYXRmb3JtTG9jYXRpb24sQEluamVjdChTUEVFQ0hSRUNPUkRFUl9DT05GSUcpIHByaXZhdGUgY29uZmlnPzpTcGVlY2hSZWNvcmRlckNvbmZpZykge1xyXG5cclxuICAgIGNvbnNvbGUubG9nKFwiQmFzZSBIcmVmOiBcIitwbGF0Zm9ybUxvY2F0aW9uLmdldEJhc2VIcmVmRnJvbURPTSgpKTtcclxuXHJcbiAgICBsZXQgYXBpRW5kUG9pbnQgPSAnJ1xyXG5cclxuICAgIGlmKGNvbmZpZyAmJiBjb25maWcuYXBpRW5kUG9pbnQpIHtcclxuICAgICAgYXBpRW5kUG9pbnQ9Y29uZmlnLmFwaUVuZFBvaW50O1xyXG4gICAgfVxyXG4gICAgaWYoYXBpRW5kUG9pbnQgIT09ICcnKXtcclxuICAgICAgYXBpRW5kUG9pbnQ9YXBpRW5kUG9pbnQrJy8nXHJcbiAgICB9XHJcbiAgICBpZihjb25maWchPW51bGwgJiYgY29uZmlnLndpdGhDcmVkZW50aWFscyE9bnVsbCl7XHJcbiAgICAgIHRoaXMud2l0aENyZWRlbnRpYWxzPWNvbmZpZy53aXRoQ3JlZGVudGlhbHM7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5wcm9qZWN0Q3R4VXJsID0gYXBpRW5kUG9pbnQgKyBQcm9qZWN0U2VydmljZS5QUk9KRUNUX0FQSV9DVFg7XHJcblxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhcHBlbmRSZXF1ZXN0VVVJREZvckRldmVsb3BtZW50U2VydmVyKHVybDpzdHJpbmcpOnN0cmluZ3tcclxuICAgIGxldCByZXNVcmw9dXJsO1xyXG4gICAgaWYgKHRoaXMuY29uZmlnICYmIHRoaXMuY29uZmlnLmFwaVR5cGUgPT09IEFwaVR5cGUuRklMRVMpIHtcclxuICAgICAgLy8gZm9yIGRldmVsb3BtZW50IGFuZCBkZW1vXHJcbiAgICAgIC8vIGFwcGVuZCBVVUlEIHRvIG1ha2UgcmVxdWVzdCBVUkwgdW5pcXVlIHRvIGF2b2lkIGxvY2FsaG9zdCBzZXJ2ZXIgY2FjaGluZ1xyXG4gICAgICByZXNVcmwgPSByZXNVcmwgKyAnLmpzb24/cmVxdWVzdFVVSUQ9JytVVUlELmdlbmVyYXRlKCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmVzVXJsXHJcbiAgfVxyXG5cclxuICBwcm9qZWN0VXJsKGlkOnN0cmluZyk6c3RyaW5ne1xyXG4gICAgbGV0IGVuY1ByaklkPWVuY29kZVVSSUNvbXBvbmVudChpZCk7XHJcbiAgICByZXR1cm4gdGhpcy5hcHBlbmRSZXF1ZXN0VVVJREZvckRldmVsb3BtZW50U2VydmVyKHRoaXMucHJvamVjdEN0eFVybCArICcvJyArIGVuY1ByaklkKTtcclxuICB9XHJcblxyXG4gIHByb2plY3RSZXNvdXJjZVVybChwcm9qZWN0SWQ6IHN0cmluZyxyZWxSZXNvdXJjZVBhdGg6c3RyaW5nKTpzdHJpbmd7XHJcbiAgICBsZXQgZW5jUHJqSWQ9ZW5jb2RlVVJJQ29tcG9uZW50KHByb2plY3RJZCk7XHJcbiAgICAvLyBVc2UgZW5jb2RlVVJJIGhlcmUgc2luY2UgdGhlIHJlbGF0aWNlIHJlc291cmNlIHBhdGggZnJvbSByZWNvcmRpbmcgc2NyaXB0cyBpcyBhbHJlYWR5IGEgVVJJXHJcbiAgICAvLyBlbmNvZGVVUklDb21wb25lbnQgZnVuY3Rpb24gd291bGQgZW5jb2RlIHRoZSBzbGFzaGVzIGFuZCBmZXRjaGluZyB0aGUgcmVzb3VyY2Ugd291bGQgZmFpbFxyXG4gICAgbGV0IGVuY1JlbFJlc1BhdGg9ZW5jb2RlVVJJKHJlbFJlc291cmNlUGF0aCk7XHJcbiAgICByZXR1cm4gdGhpcy5wcm9qZWN0Q3R4VXJsICsgJy8nICsgZW5jUHJqSWQgKycvJytlbmNSZWxSZXNQYXRoO1xyXG4gIH1cclxuXHJcbiAgcHJvamVjdE9ic2VydmFibGUoaWQ6c3RyaW5nKTpPYnNlcnZhYmxlPFByb2plY3Q+e1xyXG4gICAgbGV0IHByalVybD10aGlzLnByb2plY3RVcmwoaWQpO1xyXG4gICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PFByb2plY3Q+KHByalVybCx7d2l0aENyZWRlbnRpYWxzOiB0aGlzLndpdGhDcmVkZW50aWFsc30pXHJcbiAgIH1cclxuXHJcbn1cclxuXHJcblxyXG4iXX0=
|
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
import { UUID } from '../utils/utils';
|
|
2
|
-
export class RecordingFileDescriptorImpl {
|
|
3
|
-
constructor() { }
|
|
4
|
-
}
|
|
5
|
-
export class RecordingFile {
|
|
6
|
-
constructor(uuid, sessionId, audioDataHolder) {
|
|
7
|
-
this.recordingFileId = null;
|
|
8
|
-
this.uuid = null;
|
|
9
|
-
this.serverPersisted = false;
|
|
10
|
-
this.date = null;
|
|
11
|
-
this._dateAsDateObj = null;
|
|
12
|
-
this.startedDate = null;
|
|
13
|
-
this._startedAsDateObj = null;
|
|
14
|
-
this.audioDataHolder = null;
|
|
15
|
-
this.session = null;
|
|
16
|
-
this.channels = null;
|
|
17
|
-
this.frames = null;
|
|
18
|
-
this.samplerate = null;
|
|
19
|
-
this.timeLength = null;
|
|
20
|
-
this.editSampleRate = null;
|
|
21
|
-
this.editStartFrame = null;
|
|
22
|
-
this.editEndFrame = null;
|
|
23
|
-
this.session = sessionId;
|
|
24
|
-
this.audioDataHolder = audioDataHolder;
|
|
25
|
-
if (audioDataHolder) {
|
|
26
|
-
this.frames = audioDataHolder.frameLen;
|
|
27
|
-
this.timeLength = audioDataHolder.duration;
|
|
28
|
-
}
|
|
29
|
-
this.uuid = uuid;
|
|
30
|
-
}
|
|
31
|
-
filenameString() {
|
|
32
|
-
let fns = '';
|
|
33
|
-
if (this.session) {
|
|
34
|
-
fns += this.session;
|
|
35
|
-
fns += '_';
|
|
36
|
-
}
|
|
37
|
-
fns += this.uuid;
|
|
38
|
-
return fns;
|
|
39
|
-
}
|
|
40
|
-
equals(otherRecordingFile) {
|
|
41
|
-
if (otherRecordingFile !== null) {
|
|
42
|
-
if (otherRecordingFile === this) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
if (otherRecordingFile.uuid === this.uuid) {
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
toString() {
|
|
52
|
-
return 'Recording file: UUID: ' + this.uuid + ', session: ' + this.session;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
export class SprRecordingFile extends RecordingFile {
|
|
56
|
-
constructor(sessionId, itemcode, version, audioDataHolder) {
|
|
57
|
-
super(UUID.generate(), sessionId, audioDataHolder);
|
|
58
|
-
this.session = sessionId;
|
|
59
|
-
this.itemCode = itemcode;
|
|
60
|
-
this.version = version;
|
|
61
|
-
}
|
|
62
|
-
recordingFileDone() {
|
|
63
|
-
return (this.serverPersisted === true) || (this.audioDataHolder != null);
|
|
64
|
-
}
|
|
65
|
-
filenameString() {
|
|
66
|
-
let fns = '';
|
|
67
|
-
if (this.session) {
|
|
68
|
-
fns += this.session;
|
|
69
|
-
fns += '_';
|
|
70
|
-
}
|
|
71
|
-
if (this.itemCode) {
|
|
72
|
-
fns += this.itemCode;
|
|
73
|
-
fns += '_';
|
|
74
|
-
}
|
|
75
|
-
fns += this.uuid;
|
|
76
|
-
return fns;
|
|
77
|
-
}
|
|
78
|
-
toString() {
|
|
79
|
-
return 'Recording file: UUID: ' + this.uuid + ', session: ' + this.session + ', itemcode: ' + this.itemCode + ', version: ' + this.version + ', UUID: ' + this.uuid;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
export class RecordingFileUtils {
|
|
83
|
-
static equals(recordinFile, otherRecordingFile) {
|
|
84
|
-
if (recordinFile && otherRecordingFile) {
|
|
85
|
-
if (otherRecordingFile === recordinFile) {
|
|
86
|
-
return true;
|
|
87
|
-
}
|
|
88
|
-
if (otherRecordingFile.uuid === recordinFile.uuid) {
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
static setAudioData(rf, audioDataHolder) {
|
|
95
|
-
rf.audioDataHolder = audioDataHolder;
|
|
96
|
-
if (audioDataHolder) {
|
|
97
|
-
if (rf.samplerate == null) {
|
|
98
|
-
rf.samplerate = audioDataHolder.sampleRate;
|
|
99
|
-
}
|
|
100
|
-
if (rf.frames == null) {
|
|
101
|
-
rf.frames = audioDataHolder.frameLen;
|
|
102
|
-
}
|
|
103
|
-
rf.timeLength = audioDataHolder.duration;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
static sampleCount(rf) {
|
|
107
|
-
if (rf.audioDataHolder) {
|
|
108
|
-
return rf.audioDataHolder.sampleCounts();
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
return 0;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
static expireAudioData(rf) {
|
|
115
|
-
let expiredSamples = 0;
|
|
116
|
-
if (rf && rf.audioDataHolder) {
|
|
117
|
-
expiredSamples = rf.audioDataHolder.sampleCounts();
|
|
118
|
-
rf.audioDataHolder.releaseAudioData();
|
|
119
|
-
rf.audioDataHolder = null;
|
|
120
|
-
}
|
|
121
|
-
return expiredSamples;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
1
|
+
import { UUID } from '../utils/utils';
|
|
2
|
+
export class RecordingFileDescriptorImpl {
|
|
3
|
+
constructor() { }
|
|
4
|
+
}
|
|
5
|
+
export class RecordingFile {
|
|
6
|
+
constructor(uuid, sessionId, audioDataHolder) {
|
|
7
|
+
this.recordingFileId = null;
|
|
8
|
+
this.uuid = null;
|
|
9
|
+
this.serverPersisted = false;
|
|
10
|
+
this.date = null;
|
|
11
|
+
this._dateAsDateObj = null;
|
|
12
|
+
this.startedDate = null;
|
|
13
|
+
this._startedAsDateObj = null;
|
|
14
|
+
this.audioDataHolder = null;
|
|
15
|
+
this.session = null;
|
|
16
|
+
this.channels = null;
|
|
17
|
+
this.frames = null;
|
|
18
|
+
this.samplerate = null;
|
|
19
|
+
this.timeLength = null;
|
|
20
|
+
this.editSampleRate = null;
|
|
21
|
+
this.editStartFrame = null;
|
|
22
|
+
this.editEndFrame = null;
|
|
23
|
+
this.session = sessionId;
|
|
24
|
+
this.audioDataHolder = audioDataHolder;
|
|
25
|
+
if (audioDataHolder) {
|
|
26
|
+
this.frames = audioDataHolder.frameLen;
|
|
27
|
+
this.timeLength = audioDataHolder.duration;
|
|
28
|
+
}
|
|
29
|
+
this.uuid = uuid;
|
|
30
|
+
}
|
|
31
|
+
filenameString() {
|
|
32
|
+
let fns = '';
|
|
33
|
+
if (this.session) {
|
|
34
|
+
fns += this.session;
|
|
35
|
+
fns += '_';
|
|
36
|
+
}
|
|
37
|
+
fns += this.uuid;
|
|
38
|
+
return fns;
|
|
39
|
+
}
|
|
40
|
+
equals(otherRecordingFile) {
|
|
41
|
+
if (otherRecordingFile !== null) {
|
|
42
|
+
if (otherRecordingFile === this) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (otherRecordingFile.uuid === this.uuid) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
toString() {
|
|
52
|
+
return 'Recording file: UUID: ' + this.uuid + ', session: ' + this.session;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export class SprRecordingFile extends RecordingFile {
|
|
56
|
+
constructor(sessionId, itemcode, version, audioDataHolder) {
|
|
57
|
+
super(UUID.generate(), sessionId, audioDataHolder);
|
|
58
|
+
this.session = sessionId;
|
|
59
|
+
this.itemCode = itemcode;
|
|
60
|
+
this.version = version;
|
|
61
|
+
}
|
|
62
|
+
recordingFileDone() {
|
|
63
|
+
return (this.serverPersisted === true) || (this.audioDataHolder != null);
|
|
64
|
+
}
|
|
65
|
+
filenameString() {
|
|
66
|
+
let fns = '';
|
|
67
|
+
if (this.session) {
|
|
68
|
+
fns += this.session;
|
|
69
|
+
fns += '_';
|
|
70
|
+
}
|
|
71
|
+
if (this.itemCode) {
|
|
72
|
+
fns += this.itemCode;
|
|
73
|
+
fns += '_';
|
|
74
|
+
}
|
|
75
|
+
fns += this.uuid;
|
|
76
|
+
return fns;
|
|
77
|
+
}
|
|
78
|
+
toString() {
|
|
79
|
+
return 'Recording file: UUID: ' + this.uuid + ', session: ' + this.session + ', itemcode: ' + this.itemCode + ', version: ' + this.version + ', UUID: ' + this.uuid;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export class RecordingFileUtils {
|
|
83
|
+
static equals(recordinFile, otherRecordingFile) {
|
|
84
|
+
if (recordinFile && otherRecordingFile) {
|
|
85
|
+
if (otherRecordingFile === recordinFile) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
if (otherRecordingFile.uuid === recordinFile.uuid) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
static setAudioData(rf, audioDataHolder) {
|
|
95
|
+
rf.audioDataHolder = audioDataHolder;
|
|
96
|
+
if (audioDataHolder) {
|
|
97
|
+
if (rf.samplerate == null) {
|
|
98
|
+
rf.samplerate = audioDataHolder.sampleRate;
|
|
99
|
+
}
|
|
100
|
+
if (rf.frames == null) {
|
|
101
|
+
rf.frames = audioDataHolder.frameLen;
|
|
102
|
+
}
|
|
103
|
+
rf.timeLength = audioDataHolder.duration;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
static sampleCount(rf) {
|
|
107
|
+
if (rf.audioDataHolder) {
|
|
108
|
+
return rf.audioDataHolder.sampleCounts();
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return 0;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
static expireAudioData(rf) {
|
|
115
|
+
let expiredSamples = 0;
|
|
116
|
+
if (rf && rf.audioDataHolder) {
|
|
117
|
+
expiredSamples = rf.audioDataHolder.sampleCounts();
|
|
118
|
+
rf.audioDataHolder.releaseAudioData();
|
|
119
|
+
rf.audioDataHolder = null;
|
|
120
|
+
}
|
|
121
|
+
return expiredSamples;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
124
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3JkaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc3BlZWNocmVjb3JkZXJuZy9zcmMvbGliL3NwZWVjaHJlY29yZGVyL3JlY29yZGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFlckMsTUFBTSxPQUFPLDJCQUEyQjtJQU10QyxnQkFBZSxDQUFDO0NBQ2pCO0FBRUQsTUFBTSxPQUFPLGFBQWE7SUFrQnhCLFlBQVksSUFBVyxFQUFDLFNBQXVCLEVBQUMsZUFBb0M7UUFqQnBGLG9CQUFlLEdBQTBCLElBQUksQ0FBQztRQUM5QyxTQUFJLEdBQWEsSUFBSSxDQUFDO1FBQ3RCLG9CQUFlLEdBQUMsS0FBSyxDQUFDO1FBQ3RCLFNBQUksR0FBYyxJQUFJLENBQUM7UUFDdkIsbUJBQWMsR0FBVyxJQUFJLENBQUM7UUFDOUIsZ0JBQVcsR0FBYyxJQUFJLENBQUM7UUFDOUIsc0JBQWlCLEdBQVksSUFBSSxDQUFDO1FBQ2xDLG9CQUFlLEdBQXNCLElBQUksQ0FBQztRQUMxQyxZQUFPLEdBQW9CLElBQUksQ0FBQztRQUNoQyxhQUFRLEdBQWEsSUFBSSxDQUFDO1FBQzFCLFdBQU0sR0FBYSxJQUFJLENBQUM7UUFDeEIsZUFBVSxHQUFhLElBQUksQ0FBQztRQUM1QixlQUFVLEdBQWEsSUFBSSxDQUFDO1FBQzVCLG1CQUFjLEdBQWEsSUFBSSxDQUFDO1FBQ2hDLG1CQUFjLEdBQWEsSUFBSSxDQUFBO1FBQy9CLGlCQUFZLEdBQWEsSUFBSSxDQUFBO1FBRzNCLElBQUksQ0FBQyxPQUFPLEdBQUMsU0FBUyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxlQUFlLEdBQUMsZUFBZSxDQUFBO1FBQ3BDLElBQUcsZUFBZSxFQUFDO1lBQ2pCLElBQUksQ0FBQyxNQUFNLEdBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQztZQUNyQyxJQUFJLENBQUMsVUFB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QUMsZUFBZSxHQUFDLGVBQWUsQ0FBQztRQUNuQyxJQUFHLGVBQWUsRUFBRTtZQUNsQixJQUFHLEVBQUUsQ0FBQyxVQUFVLElBQUUsSUFBSSxFQUFDO2dCQUNyQixFQUFFLENBQUMsVUFBVSxHQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUM7YUFDMUM7WUFDRCxJQUFHLEVBQUUsQ0FBQyxNQUFNLElBQUUsSUFBSSxFQUFFO2dCQUNsQixFQUFFLENBQUMsTUFBTSxHQUFHLGVBQWUsQ0FBQyxRQUFRLENBQUM7YUFDdEM7WUFDRCxFQUFFLENBQUMsVUFBVSxHQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUM7U0FDeEM7SUFDTCxDQUFDO0lBRUQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFnQjtRQUNqQyxJQUFHLEVBQUUsQ0FBQyxlQUFlLEVBQUM7WUFDcEIsT0FBTyxFQUFFLENBQUMsZUFBZSxDQUFDLFlBQVksRUFBRSxDQUFDO1NBQzFDO2FBQUk7WUFDSCxPQUFPLENBQUMsQ0FBQztTQUNWO0lBQ0gsQ0FBQztJQUNELE1BQU0sQ0FBQyxlQUFlLENBQUMsRUFBZ0I7UUFDckMsSUFBSSxjQUFjLEdBQUMsQ0FBQyxDQUFDO1FBQ3JCLElBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQyxlQUFlLEVBQUM7WUFDMUIsY0FBYyxHQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDakQsRUFBRSxDQUFDLGVBQWUsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO1lBQ3JDLEVBQUUsQ0FBQyxlQUFlLEdBQUMsSUFBSSxDQUFDO1NBQ3pCO1FBQ0QsT0FBTyxjQUFjLENBQUM7SUFDeEIsQ0FBQztDQUVGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVVVJRCB9IGZyb20gJy4uL3V0aWxzL3V0aWxzJ1xyXG5pbXBvcnQge1Byb21wdEl0ZW19IGZyb20gXCIuL3NjcmlwdC9zY3JpcHRcIjtcclxuaW1wb3J0IHtBdWRpb0RhdGFIb2xkZXJ9IGZyb20gXCIuLi9hdWRpby9hdWRpb19kYXRhX2hvbGRlclwiO1xyXG5cclxuLy8gVE9ETyBJIHRoaW5rIHRoZSBpbnRlcmZhY2UvY2xhc3Mgc3RydWN0dXJlIG5lZWRzIHNvbWUgcmVmYWN0b3JpbmdcclxuLy8gVGhlIHF1ZXN0aW9uIGluIGdlbmVyYWwgaXMgaG93IHRvIGZldGNoIGFuIG9iamVjdCBvZiBhIGNsYXNzICh3aXRoIG1lbWJlciBtZXRob2RzKVxyXG4vLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy81MDQ1MjQzMS9hbmd1bGFyLTYtaHR0cGNsaWVudC1yZXR1cm4taW5zdGFuY2Utb2YtY2xhc3NcclxuLy8gQW5ndWxhciBIVFRQQ2xpZW50IHNlZW1zIHRvIHNpbXBseVxyXG4vLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy80NzQ5OTMyNC9hbmd1bGFyLTUtbW9kZWxzLWh0dHBjbGllbnQtdHlwZS1jYXN0aW5nXHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFJlY29yZGluZ0ZpbGVEZXNjcmlwdG9yIHtcclxuICByZWNvcmRpbmc6UHJvbXB0SXRlbTtcclxuICB2ZXJzaW9uOm51bWJlcjtcclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIFJlY29yZGluZ0ZpbGVEZXNjcmlwdG9ySW1wbCB7XHJcbiAgcmVjb3JkaW5nITpQcm9tcHRJdGVtO1xyXG4gIHZlcnNpb24hOm51bWJlcjtcclxuICBmcmFtZXM/Om51bWJlcjtcclxuICBzYW1wbGVyYXRlPzpudW1iZXI7XHJcbiAgY2hhbm5lbHM/OiBudW1iZXI7XHJcbiAgY29uc3RydWN0b3IoKSB7fVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRmlsZSB7XHJcbiAgcmVjb3JkaW5nRmlsZUlkOiBzdHJpbmcgfCBudW1iZXIgfCBudWxsPSBudWxsO1xyXG4gIHV1aWQ6c3RyaW5nfG51bGw9bnVsbDtcclxuICBzZXJ2ZXJQZXJzaXN0ZWQ9ZmFsc2U7XHJcbiAgZGF0ZTogc3RyaW5nfG51bGw9bnVsbDtcclxuICBfZGF0ZUFzRGF0ZU9iajpEYXRlfG51bGw9bnVsbDtcclxuICBzdGFydGVkRGF0ZTogc3RyaW5nfG51bGw9bnVsbDtcclxuICBfc3RhcnRlZEFzRGF0ZU9iaj86RGF0ZXxudWxsPW51bGw7XHJcbiAgYXVkaW9EYXRhSG9sZGVyOkF1ZGlvRGF0YUhvbGRlcnxudWxsPW51bGw7XHJcbiAgc2Vzc2lvbjpzdHJpbmd8bnVtYmVyfG51bGw9bnVsbDtcclxuICBjaGFubmVsczpudW1iZXJ8bnVsbD1udWxsO1xyXG4gIGZyYW1lczpudW1iZXJ8bnVsbD1udWxsO1xyXG4gIHNhbXBsZXJhdGU6bnVtYmVyfG51bGw9bnVsbDtcclxuICB0aW1lTGVuZ3RoOm51bWJlcnxudWxsPW51bGw7XHJcbiAgZWRpdFNhbXBsZVJhdGU6bnVtYmVyfG51bGw9bnVsbDtcclxuICBlZGl0U3RhcnRGcmFtZTpudW1iZXJ8bnVsbD1udWxsXHJcbiAgZWRpdEVuZEZyYW1lOm51bWJlcnxudWxsPW51bGxcclxuXHJcbiAgY29uc3RydWN0b3IodXVpZDpzdHJpbmcsc2Vzc2lvbklkOnN0cmluZ3xudW1iZXIsYXVkaW9EYXRhSG9sZGVyOkF1ZGlvRGF0YUhvbGRlcnxudWxsKSB7XHJcbiAgICB0aGlzLnNlc3Npb249c2Vzc2lvbklkO1xyXG4gICAgdGhpcy5hdWRpb0RhdGFIb2xkZXI9YXVkaW9EYXRhSG9sZGVyXHJcbiAgICBpZihhdWRpb0RhdGFIb2xkZXIpe1xyXG4gICAgICB0aGlzLmZyYW1lcz1hdWRpb0RhdGFIb2xkZXIuZnJhbWVMZW47XHJcbiAgICAgIHRoaXMudGltZUxlbmd0aD1hdWRpb0RhdGFIb2xkZXIuZHVyYXRpb247XHJcbiAgICB9XHJcbiAgICB0aGlzLnV1aWQ9dXVpZDtcclxuICB9XHJcblxyXG4gIGZpbGVuYW1lU3RyaW5nKCk6c3RyaW5ne1xyXG4gICAgbGV0IGZuczpzdHJpbmc9Jyc7XHJcbiAgICBpZih0aGlzLnNlc3Npb24pe1xyXG4gICAgICBmbnMrPXRoaXMuc2Vzc2lvbjtcclxuICAgICAgZm5zKz0nXyc7XHJcbiAgICB9XHJcbiAgICBmbnMrPXRoaXMudXVpZDtcclxuICAgIHJldHVybiBmbnM7XHJcbiAgfVxyXG5cclxuICBlcXVhbHMob3RoZXJSZWNvcmRpbmdGaWxlOlJlY29yZGluZ0ZpbGV8bnVsbCk6Ym9vbGVhbntcclxuICAgIGlmKG90aGVyUmVjb3JkaW5nRmlsZSE9PW51bGwpIHtcclxuICAgICAgaWYgKG90aGVyUmVjb3JkaW5nRmlsZSA9PT0gdGhpcykge1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChvdGhlclJlY29yZGluZ0ZpbGUudXVpZCA9PT0gdGhpcy51dWlkKSB7XHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIHRvU3RyaW5nKCk6c3RyaW5ne1xyXG4gICAgcmV0dXJuICdSZWNvcmRpbmcgZmlsZTogVVVJRDogJyt0aGlzLnV1aWQrJywgc2Vzc2lvbjogJyt0aGlzLnNlc3Npb247XHJcbiAgfVxyXG5cclxufVxyXG5cclxuICAgIGV4cG9ydCBjbGFzcyBTcHJSZWNvcmRpbmdGaWxlIGV4dGVuZHMgUmVjb3JkaW5nRmlsZSBpbXBsZW1lbnRzICBSZWNvcmRpbmdGaWxlRGVzY3JpcHRvcntcclxuXHJcbiAgICAgIGl0ZW1Db2RlOnN0cmluZztcclxuXHJcbiAgICAgIHJlY29yZGluZyE6UHJvbXB0SXRlbTtcclxuICAgICAgdmVyc2lvbiE6bnVtYmVyO1xyXG5cclxuICAgICAgY29uc3RydWN0b3Ioc2Vzc2lvbklkOnN0cmluZ3xudW1iZXIsaXRlbWNvZGU6c3RyaW5nLHZlcnNpb246bnVtYmVyLGF1ZGlvRGF0YUhvbGRlcjpBdWRpb0RhdGFIb2xkZXJ8bnVsbCkge1xyXG4gICAgICAgICAgc3VwZXIoVVVJRC5nZW5lcmF0ZSgpLHNlc3Npb25JZCxhdWRpb0RhdGFIb2xkZXIpO1xyXG4gICAgICAgICAgdGhpcy5zZXNzaW9uPXNlc3Npb25JZDtcclxuICAgICAgICAgIHRoaXMuaXRlbUNvZGU9aXRlbWNvZGU7XHJcbiAgICAgICAgICB0aGlzLnZlcnNpb249dmVyc2lvbjtcclxuICAgICAgfVxyXG5cclxuICAgICAgcmVjb3JkaW5nRmlsZURvbmUoKTpib29sZWFue1xyXG4gICAgICAgIHJldHVybiAodGhpcy5zZXJ2ZXJQZXJzaXN0ZWQ9PT10cnVlKSB8fCAodGhpcy5hdWRpb0RhdGFIb2xkZXIhPW51bGwpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBmaWxlbmFtZVN0cmluZygpOnN0cmluZ3tcclxuICAgICAgICBsZXQgZm5zOnN0cmluZz0nJztcclxuICAgICAgICBpZih0aGlzLnNlc3Npb24pe1xyXG4gICAgICAgICAgICBmbnMrPXRoaXMuc2Vzc2lvbjtcclxuICAgICAgICAgICAgZm5zKz0nXyc7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmKHRoaXMuaXRlbUNvZGUpe1xyXG4gICAgICAgICAgZm5zKz10aGlzLml0ZW1Db2RlO1xyXG4gICAgICAgICAgZm5zKz0nXyc7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZucys9dGhpcy51dWlkO1xyXG4gICAgICAgIHJldHVybiBmbnM7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRvU3RyaW5nKCk6c3RyaW5ne1xyXG4gICAgICAgIHJldHVybiAnUmVjb3JkaW5nIGZpbGU6IFVVSUQ6ICcrdGhpcy51dWlkKycsIHNlc3Npb246ICcrdGhpcy5zZXNzaW9uKycsIGl0ZW1jb2RlOiAnK3RoaXMuaXRlbUNvZGUrJywgdmVyc2lvbjogJyt0aGlzLnZlcnNpb24rJywgVVVJRDogJyt0aGlzLnV1aWQ7XHJcbiAgICAgIH1cclxuXHJcbiAgICB9XHJcblxyXG4gICAgZXhwb3J0IGNsYXNzIFJlY29yZGluZ0ZpbGVVdGlsc3tcclxuXHJcbiAgICAgIHN0YXRpYyBlcXVhbHMocmVjb3JkaW5GaWxlOlJlY29yZGluZ0ZpbGV8bnVsbCxvdGhlclJlY29yZGluZ0ZpbGU6UmVjb3JkaW5nRmlsZXxudWxsKTpib29sZWFue1xyXG4gICAgICAgIGlmKHJlY29yZGluRmlsZSAmJiBvdGhlclJlY29yZGluZ0ZpbGUpe1xyXG4gICAgICAgICAgaWYgKG90aGVyUmVjb3JkaW5nRmlsZSA9PT0gcmVjb3JkaW5GaWxlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYgKG90aGVyUmVjb3JkaW5nRmlsZS51dWlkID09PSByZWNvcmRpbkZpbGUudXVpZCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBzdGF0aWMgc2V0QXVkaW9EYXRhKHJmOlJlY29yZGluZ0ZpbGUsYXVkaW9EYXRhSG9sZGVyOkF1ZGlvRGF0YUhvbGRlcnxudWxsKXtcclxuICAgICAgICAgIHJmLmF1ZGlvRGF0YUhvbGRlcj1hdWRpb0RhdGFIb2xkZXI7XHJcbiAgICAgICAgICBpZihhdWRpb0RhdGFIb2xkZXIpIHtcclxuICAgICAgICAgICAgaWYocmYuc2FtcGxlcmF0ZT09bnVsbCl7XHJcbiAgICAgICAgICAgICAgcmYuc2FtcGxlcmF0ZT1hdWRpb0RhdGFIb2xkZXIuc2FtcGxlUmF0ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZihyZi5mcmFtZXM9PW51bGwpIHtcclxuICAgICAgICAgICAgICByZi5mcmFtZXMgPSBhdWRpb0RhdGFIb2xkZXIuZnJhbWVMZW47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmYudGltZUxlbmd0aD1hdWRpb0RhdGFIb2xkZXIuZHVyYXRpb247XHJcbiAgICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHN0YXRpYyBzYW1wbGVDb3VudChyZjpSZWNvcmRpbmdGaWxlKTpudW1iZXJ7XHJcbiAgICAgICAgaWYocmYuYXVkaW9EYXRhSG9sZGVyKXtcclxuICAgICAgICAgIHJldHVybiByZi5hdWRpb0RhdGFIb2xkZXIuc2FtcGxlQ291bnRzKCk7XHJcbiAgICAgICAgfWVsc2V7XHJcbiAgICAgICAgICByZXR1cm4gMDtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgc3RhdGljIGV4cGlyZUF1ZGlvRGF0YShyZjpSZWNvcmRpbmdGaWxlKTpudW1iZXJ7XHJcbiAgICAgICAgbGV0IGV4cGlyZWRTYW1wbGVzPTA7XHJcbiAgICAgICAgaWYocmYgJiYgcmYuYXVkaW9EYXRhSG9sZGVyKXtcclxuICAgICAgICAgIGV4cGlyZWRTYW1wbGVzPXJmLmF1ZGlvRGF0YUhvbGRlci5zYW1wbGVDb3VudHMoKTtcclxuICAgICAgICAgIHJmLmF1ZGlvRGF0YUhvbGRlci5yZWxlYXNlQXVkaW9EYXRhKClcclxuICAgICAgICAgIHJmLmF1ZGlvRGF0YUhvbGRlcj1udWxsO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gZXhwaXJlZFNhbXBsZXM7XHJcbiAgICAgIH1cclxuXHJcbiAgICB9XHJcbiJdfQ==
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
var BasicRecordingService_1;
|
|
2
|
+
import { __decorate, __param } from "tslib";
|
|
3
|
+
import { HttpHeaders } from "@angular/common/http";
|
|
4
|
+
import { Inject } from "@angular/core";
|
|
5
|
+
import { ApiType, SPEECHRECORDER_CONFIG } from "../../spr.config";
|
|
6
|
+
import { Observable } from "rxjs";
|
|
7
|
+
import { NetAudioBuffer } from "../../audio/net_audio_buffer";
|
|
8
|
+
import { UUID } from "../../utils/utils";
|
|
9
|
+
import { WavReader } from "../../audio/impl/wavreader";
|
|
10
|
+
import { AudioContextProvider } from "../../audio/context";
|
|
11
|
+
export class ChunkDownload {
|
|
12
|
+
get orgPCMAudioFormat() {
|
|
13
|
+
return this._orgPCMAudioFormat;
|
|
14
|
+
}
|
|
15
|
+
get orgFrameLength() {
|
|
16
|
+
return this._orgFrameLength;
|
|
17
|
+
}
|
|
18
|
+
get decodedAudioBuffer() {
|
|
19
|
+
return this._decodedAudioBuffer;
|
|
20
|
+
}
|
|
21
|
+
constructor(_orgPCMAudioFormat, _orgFrameLength, _decodedAudioBuffer) {
|
|
22
|
+
this._orgPCMAudioFormat = _orgPCMAudioFormat;
|
|
23
|
+
this._orgFrameLength = _orgFrameLength;
|
|
24
|
+
this._decodedAudioBuffer = _decodedAudioBuffer;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
let BasicRecordingService = class BasicRecordingService {
|
|
28
|
+
static { BasicRecordingService_1 = this; }
|
|
29
|
+
// iPad 9th generation, iOS 15.7.1, sometimes:
|
|
30
|
+
// Failed to load resource: WebKit hat einen internen Fehler festgestellt
|
|
31
|
+
// Firefox on Windows crashes
|
|
32
|
+
static { this.DEFAULT_CHUNKED_DOWNLOAD_SECONDS = 10; }
|
|
33
|
+
static { this.DEFAULT_MAX_NET_AUTO_MEM_STORE_SAMPLES = 2880000 * 5; } // Default 5 minutes one channel at 48kHz
|
|
34
|
+
constructor(http, config) {
|
|
35
|
+
this.http = http;
|
|
36
|
+
this.config = config;
|
|
37
|
+
this._maxAutoNetMemStoreSamples = BasicRecordingService_1.DEFAULT_MAX_NET_AUTO_MEM_STORE_SAMPLES;
|
|
38
|
+
this.withCredentials = false;
|
|
39
|
+
this.apiEndPoint = '';
|
|
40
|
+
if (config && config.apiEndPoint) {
|
|
41
|
+
this.apiEndPoint = config.apiEndPoint;
|
|
42
|
+
}
|
|
43
|
+
if (this.apiEndPoint !== '') {
|
|
44
|
+
this.apiEndPoint = this.apiEndPoint + '/';
|
|
45
|
+
}
|
|
46
|
+
if (config != null && config.withCredentials != null) {
|
|
47
|
+
this.withCredentials = config.withCredentials;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
audioRequestByURL(audioBaseUrl, audioURLSearchParams) {
|
|
51
|
+
let audioUrl = audioBaseUrl;
|
|
52
|
+
if (this.config && this.config.apiType === ApiType.FILES) {
|
|
53
|
+
// for development and demo
|
|
54
|
+
audioUrl = audioUrl + '.wav';
|
|
55
|
+
// append UUID to make request URL unique to avoid localhost server caching
|
|
56
|
+
audioURLSearchParams.set('requestUUID', UUID.generate());
|
|
57
|
+
//audioUrl = audioUrl + '.wav?requestUUID=' + UUID.generate();
|
|
58
|
+
}
|
|
59
|
+
audioUrl = audioUrl + '?' + audioURLSearchParams.toString();
|
|
60
|
+
let headers = new HttpHeaders();
|
|
61
|
+
headers = headers.set('Accept', 'audio/wav');
|
|
62
|
+
return this.http.get(audioUrl, {
|
|
63
|
+
headers: headers,
|
|
64
|
+
observe: 'response',
|
|
65
|
+
responseType: 'arraybuffer',
|
|
66
|
+
withCredentials: this.withCredentials
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
chunkAudioRequest(baseAudioUrl, startFrame = 0, frameLength) {
|
|
70
|
+
let ausps = new URLSearchParams();
|
|
71
|
+
ausps.set('startFrame', startFrame.toString());
|
|
72
|
+
ausps.set('frameLength', frameLength.toString());
|
|
73
|
+
if (this.config && this.config.apiType === ApiType.FILES) {
|
|
74
|
+
// for development and demo
|
|
75
|
+
// append UUID to make request URL unique to avoid localhost server caching
|
|
76
|
+
//audioUrl = audioUrl + '.wav?requestUUID=' + UUID.generate();
|
|
77
|
+
ausps.set('requestUUID', UUID.generate());
|
|
78
|
+
}
|
|
79
|
+
let obs = new Observable(observer => {
|
|
80
|
+
this.audioRequestByURL(baseAudioUrl, ausps).subscribe({
|
|
81
|
+
next: resp => {
|
|
82
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
83
|
+
if (resp.body) {
|
|
84
|
+
//console.debug("chunkAudioRequest: observer.closed: "+observer.closed);
|
|
85
|
+
//console.debug("Audio file bytes: "+resp.body.byteLength);
|
|
86
|
+
// Check original audio format
|
|
87
|
+
let wr = new WavReader(resp.body);
|
|
88
|
+
const pcmFmt = wr.readFormat();
|
|
89
|
+
const orgFl = wr.frameLength();
|
|
90
|
+
// if(pcmFmt){
|
|
91
|
+
// console.debug("Original WAVE format of download chunk: "+pcmFmt);
|
|
92
|
+
// }else{
|
|
93
|
+
// console.error("Could not read WAVE format of original download chunk!");
|
|
94
|
+
// }
|
|
95
|
+
// if(orgFl){
|
|
96
|
+
// console.debug("Original frame length of download chunk: "+orgFl);
|
|
97
|
+
// }else{
|
|
98
|
+
// console.error("Could not read WAVE format of original download chunk!");
|
|
99
|
+
// }
|
|
100
|
+
if (pcmFmt && orgFl) {
|
|
101
|
+
AudioContextProvider.decodeAudioData(resp.body).then((ab) => {
|
|
102
|
+
//console.debug("Decoded audio chunk frames: "+ab.length);
|
|
103
|
+
let chDl = new ChunkDownload(pcmFmt, orgFl, ab);
|
|
104
|
+
observer.next(chDl);
|
|
105
|
+
observer.complete();
|
|
106
|
+
}).catch(error => {
|
|
107
|
+
//if(error instanceof HttpErrorResponse) {
|
|
108
|
+
// if (error.status == 404) {
|
|
109
|
+
// // Interpret not as an error, the file ist not recorded yet
|
|
110
|
+
// observer.next(null);
|
|
111
|
+
// observer.complete()
|
|
112
|
+
// } else {
|
|
113
|
+
// // all other states are errors
|
|
114
|
+
console.error("Recordings service chunkAudioRequest error decoding audio data: " + error.name + ": " + error.message);
|
|
115
|
+
observer.error(error);
|
|
116
|
+
// }
|
|
117
|
+
// }
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const errMsg = 'Could not parse audio header for format and/or frame length of download.';
|
|
122
|
+
console.error(errMsg);
|
|
123
|
+
observer.error(errMsg);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
const errMsg = 'Fetching audio file: response has no body';
|
|
128
|
+
console.error(errMsg);
|
|
129
|
+
observer.error(errMsg);
|
|
130
|
+
}
|
|
131
|
+
}, error: (error) => {
|
|
132
|
+
// all other states are errors
|
|
133
|
+
//const errMsg='Fetching audio file HTTP error: '+error;
|
|
134
|
+
//console.error(errMsg);
|
|
135
|
+
observer.error(error);
|
|
136
|
+
//observer.complete();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
return obs;
|
|
141
|
+
}
|
|
142
|
+
chunkAudioRequestToNetAudioBuffer(baseAudioUrl, startFrame = 0, orgSampleRate, seconds, frames) {
|
|
143
|
+
//let audioUrl=baseAudioUrl+'?startFrame='+startFrame+'&frameLength='+frameLength;
|
|
144
|
+
//let audioUrl=new URL(baseAudioUrl);
|
|
145
|
+
// if(orgSampleRate!=null && frameLength%orgSampleRate>0){
|
|
146
|
+
// const errMsg='frameLength must be equal or multiple of original samplerate.';
|
|
147
|
+
// console.error(errMsg+' ('+frameLength+'%'+orgSampleRate+'=='+(frameLength%orgSampleRate)+')');
|
|
148
|
+
// throw Error(errMsg)
|
|
149
|
+
// }
|
|
150
|
+
let frameLength = orgSampleRate * Math.round(seconds);
|
|
151
|
+
let ausps = new URLSearchParams();
|
|
152
|
+
ausps.set('startFrame', startFrame.toString());
|
|
153
|
+
ausps.set('frameLength', frameLength.toString());
|
|
154
|
+
if (this.config && this.config.apiType === ApiType.FILES) {
|
|
155
|
+
// for development and demo
|
|
156
|
+
// append UUID to make request URL unique to avoid localhost server caching
|
|
157
|
+
//audioUrl = audioUrl + '.wav?requestUUID=' + UUID.generate();
|
|
158
|
+
ausps.set('requestUUID', UUID.generate());
|
|
159
|
+
}
|
|
160
|
+
let obs = new Observable(subscriber => {
|
|
161
|
+
this.audioRequestByURL(baseAudioUrl, ausps).subscribe({ next: (resp) => {
|
|
162
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
163
|
+
if (resp.body) {
|
|
164
|
+
//console.debug("chunkAudioRequestTonetAb: subscriber.closed: "+subscriber.closed);
|
|
165
|
+
//console.debug("chunkAudioRequestTonetAb: Audio file bytes: "+resp.body.byteLength);
|
|
166
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
167
|
+
//console.debug("chunkAudioRequestTonetAb: Decoded audio chunk frames for netAb: "+ab.length);
|
|
168
|
+
//console.debug("chunkAudioRequestTonetAb: Create netAb ab from chunk ab...");
|
|
169
|
+
if (frames === null) {
|
|
170
|
+
subscriber.error(new Error('Could not get frame length from recording file object'));
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
let fl = frames;
|
|
174
|
+
if (ab.sampleRate !== orgSampleRate) {
|
|
175
|
+
if (orgSampleRate && frames) {
|
|
176
|
+
fl = Math.round(ab.sampleRate * frames / orgSampleRate);
|
|
177
|
+
//console.debug("Platform sr: "+ab.sampleRate+", file sr: "+orgSampleRate+", decoded/org frame length: "+fl+"/"+frames+", ab.length: "+ab.length);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
let nab = NetAudioBuffer.fromChunkAudioBuffer(this, baseAudioUrl, ab, fl, frameLength);
|
|
181
|
+
//let rp=new ReadyProvider();
|
|
182
|
+
//nab.readyProvider=rp;
|
|
183
|
+
//rp.ready();
|
|
184
|
+
nab.ready();
|
|
185
|
+
if (nab.frameLen < frameLength) {
|
|
186
|
+
//console.debug("chunkAudioRequestTonetAb: Built netAb ab from chunk ab: First chunk shorter tha frameLength ("+netAbAudioBuffer.frameLen+"<"+frameLength+"), assuming end of data, sealing netAb ab.");
|
|
187
|
+
nab.seal();
|
|
188
|
+
}
|
|
189
|
+
subscriber.next(nab);
|
|
190
|
+
subscriber.complete();
|
|
191
|
+
}
|
|
192
|
+
}).catch(error => {
|
|
193
|
+
console.error('chunkAudioRequestToNetAb: error: ' + error);
|
|
194
|
+
//if(error instanceof HttpErrorResponse) {
|
|
195
|
+
subscriber.error(error);
|
|
196
|
+
//}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
console.error('chunkAudioRequestToNetAb: Fetching audio file: response has no body');
|
|
201
|
+
subscriber.error('chunkAudioRequestToNetAb: Fetching audio file: response has no body');
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
error: (error) => {
|
|
205
|
+
console.error('chunkAudioRequestToNetAb: error: ' + error);
|
|
206
|
+
subscriber.error(error);
|
|
207
|
+
//subscriber.complete();
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
return obs;
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
BasicRecordingService = BasicRecordingService_1 = __decorate([
|
|
215
|
+
__param(1, Inject(SPEECHRECORDER_CONFIG))
|
|
216
|
+
], BasicRecordingService);
|
|
217
|
+
export { BasicRecordingService };
|
|
218
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzaWNfcmVjb3JkaW5nLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zcGVlY2hyZWNvcmRlcm5nL3NyYy9saWIvc3BlZWNocmVjb3JkZXIvcmVjb3JkaW5ncy9iYXNpY19yZWNvcmRpbmcuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLE9BQU8sRUFBYSxXQUFXLEVBQWUsTUFBTSxzQkFBc0IsQ0FBQztBQUMzRSxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3JDLE9BQU8sRUFBQyxPQUFPLEVBQUUscUJBQXFCLEVBQXVCLE1BQU0sa0JBQWtCLENBQUM7QUFDdEYsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUNoQyxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sOEJBQThCLENBQUM7QUFDNUQsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBQ3ZDLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSw0QkFBNEIsQ0FBQztBQUVyRCxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUV6RCxNQUFNLE9BQU8sYUFBYTtJQUN4QixJQUFJLGlCQUFpQjtRQUNuQixPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQztJQUNqQyxDQUFDO0lBRUQsSUFBSSxjQUFjO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQztJQUM5QixDQUFDO0lBRUQsSUFBSSxrQkFBa0I7UUFDcEIsT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQUM7SUFDbEMsQ0FBQztJQUNELFlBQW9CLGtCQUFpQyxFQUFTLGVBQXNCLEVBQVMsbUJBQStCO1FBQXhHLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBZTtRQUFTLG9CQUFlLEdBQWYsZUFBZSxDQUFPO1FBQVMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFZO0lBQUUsQ0FB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QztRQUNILE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQzs7QUFyTVEscUJBQXFCO0lBVVcsV0FBQSxNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQTtHQVY3RCxxQkFBcUIsQ0F1TWpDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtIdHRwQ2xpZW50LCBIdHRwSGVhZGVycywgSHR0cFJlc3BvbnNlfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uL2h0dHBcIjtcclxuaW1wb3J0IHtJbmplY3R9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7QXBpVHlwZSwgU1BFRUNIUkVDT1JERVJfQ09ORklHLCBTcGVlY2hSZWNvcmRlckNvbmZpZ30gZnJvbSBcIi4uLy4uL3Nwci5jb25maWdcIjtcclxuaW1wb3J0IHtPYnNlcnZhYmxlfSBmcm9tIFwicnhqc1wiO1xyXG5pbXBvcnQge05ldEF1ZGlvQnVmZmVyfSBmcm9tIFwiLi4vLi4vYXVkaW8vbmV0X2F1ZGlvX2J1ZmZlclwiO1xyXG5pbXBvcnQge1VVSUR9IGZyb20gXCIuLi8uLi91dGlscy91dGlsc1wiO1xyXG5pbXBvcnQge1dhdlJlYWRlcn0gZnJvbSBcIi4uLy4uL2F1ZGlvL2ltcGwvd2F2cmVhZGVyXCI7XHJcbmltcG9ydCB7UENNQXVkaW9Gb3JtYXR9IGZyb20gXCIuLi8uLi9hdWRpby9mb3JtYXRcIjtcclxuaW1wb3J0IHtBdWRpb0NvbnRleHRQcm92aWRlcn0gZnJvbSBcIi4uLy4uL2F1ZGlvL2NvbnRleHRcIjtcclxuXHJcbmV4cG9ydCBjbGFzcyBDaHVua0Rvd25sb2Fke1xyXG4gIGdldCBvcmdQQ01BdWRpb0Zvcm1hdCgpOiBQQ01BdWRpb0Zvcm1hdCB7XHJcbiAgICByZXR1cm4gdGhpcy5fb3JnUENNQXVkaW9Gb3JtYXQ7XHJcbiAgfVxyXG5cclxuICBnZXQgb3JnRnJhbWVMZW5ndGgoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLl9vcmdGcmFtZUxlbmd0aDtcclxuICB9XHJcblxyXG4gIGdldCBkZWNvZGVkQXVkaW9CdWZmZXIoKTogQXVkaW9CdWZmZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX2RlY29kZWRBdWRpb0J1ZmZlcjtcclxuICB9XHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfb3JnUENNQXVkaW9Gb3JtYXQ6UENNQXVkaW9Gb3JtYXQscHJpdmF0ZSBfb3JnRnJhbWVMZW5ndGg6bnVtYmVyLHByaXZhdGUgX2RlY29kZWRBdWRpb0J1ZmZlcjpBdWRpb0J1ZmZlcil7fVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgQmFzaWNSZWNvcmRpbmdTZXJ2aWNle1xyXG4gIC8vIGlQYWQgOXRoIGdlbmVyYXRpb24sIGlPUyAxNS43LjEsIHNvbWV0aW1lczpcclxuICAvLyBGYWlsZWQgdG8gbG9hZCByZXNvdXJjZTogV2ViS2l0IGhhdCBlaW5lbiBpbnRlcm5lbiBGZWhsZXIgZmVzdGdlc3RlbGx0XHJcbiAgLy8gRmlyZWZveCBvbiBXaW5kb3dzIGNyYXNoZXNcclxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfQ0hVTktFRF9ET1dOTE9BRF9TRUNPTkRTOm51bWJlcj0xMDtcclxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfTUFYX05FVF9BVVRPX01FTV9TVE9SRV9TQU1QTEVTOm51bWJlcj0yODgwMDAwKjU7IC8vIERlZmF1bHQgNSBtaW51dGVzIG9uZSBjaGFubmVsIGF0IDQ4a0h6XHJcbiAgcHJvdGVjdGVkIF9tYXhBdXRvTmV0TWVtU3RvcmVTYW1wbGVzOm51bWJlcj1CYXNpY1JlY29yZGluZ1NlcnZpY2UuREVGQVVMVF9NQVhfTkVUX0FVVE9fTUVNX1NUT1JFX1NBTVBMRVM7XHJcbiAgICBwcm90ZWN0ZWQgYXBpRW5kUG9pbnQ6IHN0cmluZztcclxuICAgIHByb3RlY3RlZCB3aXRoQ3JlZGVudGlhbHM6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgaHR0cDogSHR0cENsaWVudCwgQEluamVjdChTUEVFQ0hSRUNPUkRFUl9DT05GSUcpIHByb3RlY3RlZCBjb25maWc/OiBTcGVlY2hSZWNvcmRlckNvbmZpZykge1xyXG4gICAgICAgIHRoaXMuYXBpRW5kUG9pbnQgPSAnJ1xyXG5cclxuICAgICAgICBpZiAoY29uZmlnICYmIGNvbmZpZy5hcGlFbmRQb2ludCkge1xyXG4gICAgICAgICAgICB0aGlzLmFwaUVuZFBvaW50ID0gY29uZmlnLmFwaUVuZFBvaW50O1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodGhpcy5hcGlFbmRQb2ludCAhPT0gJycpIHtcclxuICAgICAgICAgICAgdGhpcy5hcGlFbmRQb2ludCA9IHRoaXMuYXBpRW5kUG9pbnQgKyAnLydcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGNvbmZpZyAhPSBudWxsICYmIGNvbmZpZy53aXRoQ3JlZGVudGlhbHMgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICB0aGlzLndpdGhDcmVkZW50aWFscyA9IGNvbmZpZy53aXRoQ3JlZGVudGlhbHM7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByb3RlY3RlZCBhdWRpb1JlcXVlc3RCeVVSTChhdWRpb0Jhc2VVcmw6c3RyaW5nLGF1ZGlvVVJMU2VhcmNoUGFyYW1zOlVSTFNlYXJjaFBhcmFtcyk6IE9ic2VydmFibGU8SHR0cFJlc3BvbnNlPEFycmF5QnVmZmVyPj4ge1xyXG4gICAgICAgIGxldCBhdWRpb1VybD1hdWRpb0Jhc2VVcmw7XHJcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnICYmIHRoaXMuY29uZmlnLmFwaVR5cGUgPT09IEFwaVR5cGUuRklMRVMpIHtcclxuICAgICAgICAgICAgLy8gZm9yIGRldmVsb3BtZW50IGFuZCBkZW1vXHJcbiAgICAgICAgICAgIGF1ZGlvVXJsPWF1ZGlvVXJsKycud2F2JztcclxuICAgICAgICAgICAgLy8gYXBwZW5kIFVVSUQgdG8gbWFrZSByZXF1ZXN0IFVSTCB1bmlxdWUgdG8gYXZvaWQgbG9jYWxob3N0IHNlcnZlciBjYWNoaW5nXHJcbiAgICAgICAgICAgIGF1ZGlvVVJMU2VhcmNoUGFyYW1zLnNldCgncmVxdWVzdFVVSUQnLFVVSUQuZ2VuZXJhdGUoKSk7XHJcbiAgICAgICAgICAgIC8vYXVkaW9VcmwgPSBhdWRpb1VybCArICcud2F2P3JlcXVlc3RVVUlEPScgKyBVVUlELmdlbmVyYXRlKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBhdWRpb1VybD1hdWRpb1VybCsnPycrYXVkaW9VUkxTZWFyY2hQYXJhbXMudG9TdHJpbmcoKTtcclxuXHJcbiAgICAgICAgbGV0IGhlYWRlcnMgPSBuZXcgSHR0cEhlYWRlcnMoKTtcclxuICAgICAgICBoZWFkZXJzID0gaGVhZGVycy5zZXQoJ0FjY2VwdCcsICdhdWRpby93YXYnKTtcclxuICAgICAgICByZXR1cm4gdGhpcy5odHRwLmdldChhdWRpb1VybCwge1xyXG4gICAgICAgICAgICBoZWFkZXJzOiBoZWFkZXJzLFxyXG4gICAgICAgICAgICBvYnNlcnZlOiAncmVzcG9uc2UnLFxyXG4gICAgICAgICAgICByZXNwb25zZVR5cGU6ICdhcnJheWJ1ZmZlcicsXHJcbiAgICAgICAgICAgIHdpdGhDcmVkZW50aWFsczogdGhpcy53aXRoQ3JlZGVudGlhbHNcclxuICAgICAgICB9KTtcclxuXHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGNodW5rQXVkaW9SZXF1ZXN0KGJhc2VBdWRpb1VybDpzdHJpbmcsc3RhcnRGcmFtZTpudW1iZXI9MCxmcmFtZUxlbmd0aDpudW1iZXIpOiBPYnNlcnZhYmxlPENodW5rRG93bmxvYWR8bnVsbD4ge1xyXG5cclxuICAgICAgICBsZXQgYXVzcHM9bmV3IFVSTFNlYXJjaFBhcmFtcygpO1xyXG4gICAgICAgIGF1c3BzLnNldCgnc3RhcnRGcmFtZScsc3RhcnRGcmFtZS50b1N0cmluZygpKTtcclxuICAgICAgICBhdXNwcy5zZXQoJ2ZyYW1lTGVuZ3RoJyxmcmFtZUxlbmd0aC50b1N0cmluZygpKTtcclxuICAgICAgICBpZiAodGhpcy5jb25maWcgJiYgdGhpcy5jb25maWcuYXBpVHlwZSA9PT0gQXBpVHlwZS5GSUxFUykge1xyXG4gICAgICAgICAgICAvLyBmb3IgZGV2ZWxvcG1lbnQgYW5kIGRlbW9cclxuICAgICAgICAgICAgLy8gYXBwZW5kIFVVSUQgdG8gbWFrZSByZXF1ZXN0IFVSTCB1bmlxdWUgdG8gYXZvaWQgbG9jYWxob3N0IHNlcnZlciBjYWNoaW5nXHJcbiAgICAgICAgICAgIC8vYXVkaW9VcmwgPSBhdWRpb1VybCArICcud2F2P3JlcXVlc3RVVUlEPScgKyBVVUlELmdlbmVyYXRlKCk7XHJcbiAgICAgICAgICAgIGF1c3BzLnNldCgncmVxdWVzdFVVSUQnLFVVSUQuZ2VuZXJhdGUoKSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgb2JzPW5ldyBPYnNlcnZhYmxlPENodW5rRG93bmxvYWR8bnVsbD4ob2JzZXJ2ZXI9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuYXVkaW9SZXF1ZXN0QnlVUkwoYmFzZUF1ZGlvVXJsLGF1c3BzKS5zdWJzY3JpYmUoXHJcbiAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgbmV4dDogcmVzcCA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvIG5vdCB1c2UgUHJvbWlzZSB2ZXJzaW9uLCB3aGljaCBkb2VzIG5vdCB3b3JrIHdpdGggU2FmYXJpIDEzICgxMy4wLjUpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXNwLmJvZHkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcImNodW5rQXVkaW9SZXF1ZXN0OiBvYnNlcnZlci5jbG9zZWQ6IFwiK29ic2VydmVyLmNsb3NlZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJBdWRpbyBmaWxlIGJ5dGVzOiBcIityZXNwLmJvZHkuYnl0ZUxlbmd0aCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgb3JpZ2luYWwgYXVkaW8gZm9ybWF0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgd3IgPSBuZXcgV2F2UmVhZGVyKHJlc3AuYm9keSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwY21GbXQgPSB3ci5yZWFkRm9ybWF0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvcmdGbCA9IHdyLmZyYW1lTGVuZ3RoKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZihwY21GbXQpe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICBjb25zb2xlLmRlYnVnKFwiT3JpZ2luYWwgV0FWRSBmb3JtYXQgb2YgZG93bmxvYWQgY2h1bms6IFwiK3BjbUZtdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB9ZWxzZXtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgY29uc29sZS5lcnJvcihcIkNvdWxkIG5vdCByZWFkIFdBVkUgZm9ybWF0IG9mIG9yaWdpbmFsIGRvd25sb2FkIGNodW5rIVwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmKG9yZ0ZsKXtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgY29uc29sZS5kZWJ1ZyhcIk9yaWdpbmFsIGZyYW1lIGxlbmd0aCBvZiBkb3dubG9hZCBjaHVuazogXCIrb3JnRmwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gfWVsc2V7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgIGNvbnNvbGUuZXJyb3IoXCJDb3VsZCBub3QgcmVhZCBXQVZFIGZvcm1hdCBvZiBvcmlnaW5hbCBkb3dubG9hZCBjaHVuayFcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBjbUZtdCAmJiBvcmdGbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdWRpb0NvbnRleHRQcm92aWRlci5kZWNvZGVBdWRpb0RhdGEocmVzcC5ib2R5KS50aGVuKChhYik9PntcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJEZWNvZGVkIGF1ZGlvIGNodW5rIGZyYW1lczogXCIrYWIubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgY2hEbCA9IG5ldyBDaHVua0Rvd25sb2FkKHBjbUZtdCwgb3JnRmwsIGFiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KGNoRGwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2lmKGVycm9yIGluc3RhbmNlb2YgSHR0cEVycm9yUmVzcG9uc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiAoZXJyb3Iuc3RhdHVzID09IDQwNCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgLy8gSW50ZXJwcmV0IG5vdCBhcyBhbiBlcnJvciwgdGhlIGZpbGUgaXN0IG5vdCByZWNvcmRlZCB5ZXRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgIG9ic2VydmVyLm5leHQobnVsbCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICBvYnNlcnZlci5jb21wbGV0ZSgpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgIC8vIGFsbCBvdGhlciBzdGF0ZXMgYXJlIGVycm9yc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJSZWNvcmRpbmdzIHNlcnZpY2UgY2h1bmtBdWRpb1JlcXVlc3QgZXJyb3IgZGVjb2RpbmcgYXVkaW8gZGF0YTogXCIgKyBlcnJvci5uYW1lICsgXCI6IFwiICsgZXJyb3IubWVzc2FnZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJNc2cgPSAnQ291bGQgbm90IHBhcnNlIGF1ZGlvIGhlYWRlciBmb3IgZm9ybWF0IGFuZC9vciBmcmFtZSBsZW5ndGggb2YgZG93bmxvYWQuJztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVyck1zZyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyTXNnKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVyck1zZyA9ICdGZXRjaGluZyBhdWRpbyBmaWxlOiByZXNwb25zZSBoYXMgbm8gYm9keSc7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVyck1zZyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcihlcnJNc2cpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSwgZXJyb3I6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWxsIG90aGVyIHN0YXRlcyBhcmUgZXJyb3JzXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2NvbnN0IGVyck1zZz0nRmV0Y2hpbmcgYXVkaW8gZmlsZSBIVFRQIGVycm9yOiAnK2Vycm9yO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmVycm9yKGVyck1zZyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcihlcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL29ic2VydmVyLmNvbXBsZXRlKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgICAgICByZXR1cm4gb2JzO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICBwcm90ZWN0ZWQgY2h1bmtBdWRpb1JlcXVlc3RUb05ldEF1ZGlvQnVmZmVyKGJhc2VBdWRpb1VybDogc3RyaW5nLCBzdGFydEZyYW1lOiBudW1iZXIgPSAwLCBvcmdTYW1wbGVSYXRlOiBudW1iZXIsIHNlY29uZHM6bnVtYmVyLGZyYW1lczogbnVtYmVyIHwgbnVsbCk6IE9ic2VydmFibGU8TmV0QXVkaW9CdWZmZXIgfCBudWxsPiB7XHJcbiAgICAgICAgLy9sZXQgYXVkaW9Vcmw9YmFzZUF1ZGlvVXJsKyc/c3RhcnRGcmFtZT0nK3N0YXJ0RnJhbWUrJyZmcmFtZUxlbmd0aD0nK2ZyYW1lTGVuZ3RoO1xyXG4gICAgICAgIC8vbGV0IGF1ZGlvVXJsPW5ldyBVUkwoYmFzZUF1ZGlvVXJsKTtcclxuICAgICAgICAvLyBpZihvcmdTYW1wbGVSYXRlIT1udWxsICYmIGZyYW1lTGVuZ3RoJW9yZ1NhbXBsZVJhdGU+MCl7XHJcbiAgICAgICAgLy8gICBjb25zdCBlcnJNc2c9J2ZyYW1lTGVuZ3RoIG11c3QgYmUgZXF1YWwgb3IgbXVsdGlwbGUgb2Ygb3JpZ2luYWwgc2FtcGxlcmF0ZS4nO1xyXG4gICAgICAgIC8vICAgY29uc29sZS5lcnJvcihlcnJNc2crJyAoJytmcmFtZUxlbmd0aCsnJScrb3JnU2FtcGxlUmF0ZSsnPT0nKyhmcmFtZUxlbmd0aCVvcmdTYW1wbGVSYXRlKSsnKScpO1xyXG4gICAgICAgIC8vICAgdGhyb3cgRXJyb3IoZXJyTXNnKVxyXG4gICAgICAgIC8vIH1cclxuICAgICAgICBsZXQgZnJhbWVMZW5ndGg6bnVtYmVyPW9yZ1NhbXBsZVJhdGUqTWF0aC5yb3VuZChzZWNvbmRzKTtcclxuICAgICAgICBsZXQgYXVzcHM9bmV3IFVSTFNlYXJjaFBhcmFtcygpO1xyXG4gICAgICAgIGF1c3BzLnNldCgnc3RhcnRGcmFtZScsc3RhcnRGcmFtZS50b1N0cmluZygpKTtcclxuICAgICAgICBhdXNwcy5zZXQoJ2ZyYW1lTGVuZ3RoJyxmcmFtZUxlbmd0aC50b1N0cmluZygpKTtcclxuICAgICAgICBpZiAodGhpcy5jb25maWcgJiYgdGhpcy5jb25maWcuYXBpVHlwZSA9PT0gQXBpVHlwZS5GSUxFUykge1xyXG4gICAgICAgICAgICAvLyBmb3IgZGV2ZWxvcG1lbnQgYW5kIGRlbW9cclxuICAgICAgICAgICAgLy8gYXBwZW5kIFVVSUQgdG8gbWFrZSByZXF1ZXN0IFVSTCB1bmlxdWUgdG8gYXZvaWQgbG9jYWxob3N0IHNlcnZlciBjYWNoaW5nXHJcbiAgICAgICAgICAgIC8vYXVkaW9VcmwgPSBhdWRpb1VybCArICcud2F2P3JlcXVlc3RVVUlEPScgKyBVVUlELmdlbmVyYXRlKCk7XHJcbiAgICAgICAgICAgIGF1c3BzLnNldCgncmVxdWVzdFVVSUQnLFVVSUQuZ2VuZXJhdGUoKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGxldCBvYnM9bmV3IE9ic2VydmFibGU8TmV0QXVkaW9CdWZmZXJ8bnVsbD4oc3Vic2NyaWJlcj0+IHtcclxuICAgICAgICAgICAgdGhpcy5hdWRpb1JlcXVlc3RCeVVSTChiYXNlQXVkaW9VcmwsYXVzcHMpLnN1YnNjcmliZSh7bmV4dDoocmVzcCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIERvIG5vdCB1c2UgUHJvbWlzZSB2ZXJzaW9uLCB3aGljaCBkb2VzIG5vdCB3b3JrIHdpdGggU2FmYXJpIDEzICgxMy4wLjUpXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3AuYm9keSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJjaHVua0F1ZGlvUmVxdWVzdFRvbmV0QWI6IHN1YnNjcmliZXIuY2xvc2VkOiBcIitzdWJzY3JpYmVyLmNsb3NlZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcImNodW5rQXVkaW9SZXF1ZXN0VG9uZXRBYjogQXVkaW8gZmlsZSBieXRlczogXCIrcmVzcC5ib2R5LmJ5dGVMZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBBdWRpb0NvbnRleHRQcm92aWRlci5kZWNvZGVBdWRpb0RhdGEocmVzcC5ib2R5KS50aGVuKGFiID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJjaHVua0F1ZGlvUmVxdWVzdFRvbmV0QWI6IERlY29kZWQgYXVkaW8gY2h1bmsgZnJhbWVzIGZvciBuZXRBYjogXCIrYWIubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUuZGVidWcoXCJjaHVua0F1ZGlvUmVxdWVzdFRvbmV0QWI6IENyZWF0ZSBuZXRBYiBhYiBmcm9tIGNodW5rIGFiLi4uXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGZyYW1lcz09PW51bGwpe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKG5ldyBFcnJvcignQ291bGQgbm90IGdldCBmcmFtZSBsZW5ndGggZnJvbSByZWNvcmRpbmcgZmlsZSBvYmplY3QnKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfWVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmwgPSBmcmFtZXM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhYi5zYW1wbGVSYXRlICE9PSBvcmdTYW1wbGVSYXRlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3JnU2FtcGxlUmF0ZSAmJiBmcmFtZXMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbCA9IE1hdGgucm91bmQoYWIuc2FtcGxlUmF0ZSAqIGZyYW1lcyAvIG9yZ1NhbXBsZVJhdGUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5kZWJ1ZyhcIlBsYXRmb3JtIHNyOiBcIithYi5zYW1wbGVSYXRlK1wiLCBmaWxlIHNyOiBcIitvcmdTYW1wbGVSYXRlK1wiLCBkZWNvZGVkL29yZyBmcmFtZSBsZW5ndGg6IFwiK2ZsK1wiL1wiK2ZyYW1lcytcIiwgYWIubGVuZ3RoOiBcIithYi5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgbmFiID0gTmV0QXVkaW9CdWZmZXIuZnJvbUNodW5rQXVkaW9CdWZmZXIodGhpcyxiYXNlQXVkaW9VcmwsIGFiLCBmbCxmcmFtZUxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vbGV0IHJwPW5ldyBSZWFkeVByb3ZpZGVyKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vbmFiLnJlYWR5UHJvdmlkZXI9cnA7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vcnAucmVhZHkoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFiLnJlYWR5KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuYWIuZnJhbWVMZW4gPCBmcmFtZUxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmRlYnVnKFwiY2h1bmtBdWRpb1JlcXVlc3RUb25ldEFiOiBCdWlsdCBuZXRBYiBhYiBmcm9tIGNodW5rIGFiOiBGaXJzdCBjaHVuayBzaG9ydGVyIHRoYSBmcmFtZUxlbmd0aCAoXCIrbmV0QWJBdWRpb0J1ZmZlci5mcmFtZUxlbitcIjxcIitmcmFtZUxlbmd0aCtcIiksIGFzc3VtaW5nIGVuZCBvZiBkYXRhLCBzZWFsaW5nIG5ldEFiIGFiLlwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hYi5zZWFsKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlci5uZXh0KG5hYik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ2NodW5rQXVkaW9SZXF1ZXN0VG9OZXRBYjogZXJyb3I6ICcrZXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vaWYoZXJyb3IgaW5zdGFuY2VvZiBIdHRwRXJyb3JSZXNwb25zZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuZXJyb3IoZXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdjaHVua0F1ZGlvUmVxdWVzdFRvTmV0QWI6IEZldGNoaW5nIGF1ZGlvIGZpbGU6IHJlc3BvbnNlIGhhcyBubyBib2R5Jyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuZXJyb3IoJ2NodW5rQXVkaW9SZXF1ZXN0VG9OZXRBYjogRmV0Y2hpbmcgYXVkaW8gZmlsZTogcmVzcG9uc2UgaGFzIG5vIGJvZHknKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgZXJyb3I6KGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignY2h1bmtBdWRpb1JlcXVlc3RUb05ldEFiOiBlcnJvcjogJytlcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlci5lcnJvcihlcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9zdWJzY3JpYmVyLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHJldHVybiBvYnM7XHJcbiAgICB9XHJcblxyXG59XHJcbiJdfQ==
|