@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
127 lines • 20.2 kB
JavaScript
import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import * as i0 from "@angular/core";
export class AudioService {
constructor() {
this._http = inject(HttpClient);
}
getAudioFileMetadata(mediaElement) {
return Observable.create((observer) => {
this._http.get(mediaElement.src, { responseType: 'blob' }).subscribe(response => {
let description;
const extension = mediaElement.src.substring(mediaElement.src.lastIndexOf('.') + 1).toLowerCase();
const filename = mediaElement.src.indexOf('base64') !== -1 ? '' : mediaElement.src.substring(mediaElement.src.lastIndexOf('/') + 1);
switch (extension) {
case 'mp3':
description = 'MPEG audio layer 3 file';
break;
case 'wma':
description = 'Windows media audio file';
break;
case 'wav':
description = 'WAVE audio file';
break;
case 'ogg':
description = 'Ogg Vorbis file';
break;
case 'aac':
description = 'Advanced audio coding file';
break;
case 'midi':
description = 'Musical instrument digital interface file';
break;
default:
description = 'Audio file';
break;
}
observer.next({
filename,
extension,
description,
size: response.size
});
});
});
}
getWaveformFromUrl(url) {
// if audio context is not support return a stream of empty data
if (!window.AudioContext) {
return of([new Float32Array(0)]);
}
this._audioContext = new AudioContext();
this.createVolumeNode();
this.createAnalyserNode();
return Observable.create((observer) => {
// load the media from the URL provided
this._http.get(url, { responseType: 'arraybuffer' }).subscribe(response => {
this.getAudioBuffer(response).subscribe(audioBuffer => {
// create the buffer source
this.createBufferSource(audioBuffer);
let dataPoints = [];
const channels = this._audioBuffer.numberOfChannels;
// extract the data from each channel
for (let channelIdx = 0; channelIdx < channels; channelIdx++) {
dataPoints[channelIdx] = this._audioBuffer.getChannelData(channelIdx);
}
observer.next(dataPoints);
observer.complete();
// cleanup after ourselves
dataPoints = null;
}, (error) => observer.error(error));
}, (error) => observer.error(error));
});
}
getWaveformPoints(channels = [], skip = 1000) {
const waveform = [];
const duration = channels.length > 0 ? channels[0].length : 0;
// convert each channel data to a series of waveform points
for (let idx = 0; idx < duration; idx += skip) {
// get all the channel data for a specific point
const points = channels.map(channel => channel[idx]);
// find the minimum point and maximum points at each position across all channels
waveform.push({
min: points.reduce((previous, current) => current < previous ? current : previous),
max: points.reduce((previous, current) => current > previous ? current : previous)
});
}
return waveform;
}
getAudioBuffer(arrayBuffer) {
return Observable.create((observer) => {
this.getOfflineAudioContext().decodeAudioData(arrayBuffer, (audioBuffer) => {
observer.next(audioBuffer);
observer.complete();
}, (error) => observer.error(error));
});
}
getOfflineAudioContext() {
return new OfflineAudioContext(1, 2, this._audioContext.sampleRate || 44100);
}
createBufferSource(audioBuffer) {
this.disconnectSource();
this._audioBuffer = audioBuffer;
this._audioBufferSource = this._audioContext.createBufferSource();
this._audioBufferSource.buffer = this._audioBuffer;
this._audioBufferSource.connect(this._analyserNode);
}
createVolumeNode() {
this._gainNode = this._audioContext.createGain();
this._gainNode.connect(this._audioContext.destination);
}
createAnalyserNode() {
this._analyserNode = this._audioContext.createAnalyser();
this._analyserNode.connect(this._gainNode);
}
disconnectSource() {
if (this._audioBufferSource) {
this._audioBufferSource.disconnect();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: AudioService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: AudioService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: AudioService, decorators: [{
type: Injectable
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaW8uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9zZXJ2aWNlcy9hdWRpby9hdWRpby5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQUUsVUFBVSxFQUFZLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7QUFHaEQsTUFBTSxPQUFPLFlBQVk7SUFEekI7UUFFcUIsVUFBSyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztLQXdKL0M7SUFoSkcsb0JBQW9CLENBQUMsWUFBOEI7UUFDL0MsT0FBTyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBaUMsRUFBRSxFQUFFO1lBQzNELElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEVBQUU7Z0JBRTVFLElBQUksV0FBVyxDQUFDO2dCQUNoQixNQUFNLFNBQVMsR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbEcsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFD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ekMsQ0FBQztJQUNMLENBQUM7K0dBeEpRLFlBQVk7bUhBQVosWUFBWTs7NEZBQVosWUFBWTtrQkFEeEIsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBpbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUsIE9ic2VydmVyLCBvZiB9IGZyb20gJ3J4anMnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXVkaW9TZXJ2aWNlIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9odHRwID0gaW5qZWN0KEh0dHBDbGllbnQpO1xuXG4gICAgcHJpdmF0ZSBfYXVkaW9CdWZmZXI6IEF1ZGlvQnVmZmVyO1xuICAgIHByaXZhdGUgX2F1ZGlvQnVmZmVyU291cmNlOiBBdWRpb0J1ZmZlclNvdXJjZU5vZGU7XG4gICAgcHJpdmF0ZSBfYXVkaW9Db250ZXh0OiBBdWRpb0NvbnRleHQ7XG4gICAgcHJpdmF0ZSBfZ2Fpbk5vZGU6IEdhaW5Ob2RlO1xuICAgIHByaXZhdGUgX2FuYWx5c2VyTm9kZTogQW5hbHlzZXJOb2RlO1xuXG4gICAgZ2V0QXVkaW9GaWxlTWV0YWRhdGEobWVkaWFFbGVtZW50OiBIVE1MTWVkaWFFbGVtZW50KTogT2JzZXJ2YWJsZTxBdWRpb01ldGFkYXRhPiB7XG4gICAgICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZSgob2JzZXJ2ZXI6IE9ic2VydmVyPEF1ZGlvTWV0YWRhdGE+KSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9odHRwLmdldChtZWRpYUVsZW1lbnQuc3JjLCB7IHJlc3BvbnNlVHlwZTogJ2Jsb2InIH0pLnN1YnNjcmliZShyZXNwb25zZSA9PiB7XG5cbiAgICAgICAgICAgICAgICBsZXQgZGVzY3JpcHRpb247XG4gICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uID0gbWVkaWFFbGVtZW50LnNyYy5zdWJzdHJpbmcobWVkaWFFbGVtZW50LnNyYy5sYXN0SW5kZXhPZignLicpICsgMSkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBmaWxlbmFtZSA9IG1lZGlhRWxlbWVudC5zcmMuaW5kZXhPZignYmFzZTY0JykgIT09IC0xID8gJycgOiBtZWRpYUVsZW1lbnQuc3JjLnN1YnN0cmluZyhtZWRpYUVsZW1lbnQuc3JjLmxhc3RJbmRleE9mKCcvJykgKyAxKTtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAoZXh0ZW5zaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21wMyc6XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiA9ICdNUEVHIGF1ZGlvIGxheWVyIDMgZmlsZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICBjYXNlICd3bWEnOlxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAnV2luZG93cyBtZWRpYSBhdWRpbyBmaWxlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3dhdic6XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiA9ICdXQVZFIGF1ZGlvIGZpbGUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnb2dnJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uID0gJ09nZyBWb3JiaXMgZmlsZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICBjYXNlICdhYWMnOlxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAnQWR2YW5jZWQgYXVkaW8gY29kaW5nIGZpbGUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbWlkaSc6XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiA9ICdNdXNpY2FsIGluc3RydW1lbnQgZGlnaXRhbCBpbnRlcmZhY2UgZmlsZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAnQXVkaW8gZmlsZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHtcbiAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWUsXG4gICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvbixcbiAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24sXG4gICAgICAgICAgICAgICAgICAgIHNpemU6IHJlc3BvbnNlLnNpemVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBnZXRXYXZlZm9ybUZyb21VcmwodXJsOiBzdHJpbmcpOiBPYnNlcnZhYmxlPEZsb2F0MzJBcnJheVtdPiB7XG5cbiAgICAgICAgLy8gaWYgYXVkaW8gY29udGV4dCBpcyBub3Qgc3VwcG9ydCByZXR1cm4gYSBzdHJlYW0gb2YgZW1wdHkgZGF0YVxuICAgICAgICBpZiAoIXdpbmRvdy5BdWRpb0NvbnRleHQpIHtcbiAgICAgICAgICAgIHJldHVybiBvZjxGbG9hdDMyQXJyYXlbXT4oW25ldyBGbG9hdDMyQXJyYXkoMCldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2F1ZGlvQ29udGV4dCA9IG5ldyBBdWRpb0NvbnRleHQoKTtcbiAgICAgICAgdGhpcy5jcmVhdGVWb2x1bWVOb2RlKCk7XG4gICAgICAgIHRoaXMuY3JlYXRlQW5hbHlzZXJOb2RlKCk7XG5cbiAgICAgICAgcmV0dXJuIE9ic2VydmFibGUuY3JlYXRlKChvYnNlcnZlcjogT2JzZXJ2ZXI8RmxvYXQzMkFycmF5W10+KSA9PiB7XG5cbiAgICAgICAgICAgIC8vIGxvYWQgdGhlIG1lZGlhIGZyb20gdGhlIFVSTCBwcm92aWRlZFxuICAgICAgICAgICAgdGhpcy5faHR0cC5nZXQodXJsLCB7IHJlc3BvbnNlVHlwZTogJ2FycmF5YnVmZmVyJyB9KS5zdWJzY3JpYmUocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZ2V0QXVkaW9CdWZmZXIocmVzcG9uc2UpLnN1YnNjcmliZShhdWRpb0J1ZmZlciA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gY3JlYXRlIHRoZSBidWZmZXIgc291cmNlXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlQnVmZmVyU291cmNlKGF1ZGlvQnVmZmVyKTtcblxuICAgICAgICAgICAgICAgICAgICBsZXQgZGF0YVBvaW50czogRmxvYXQzMkFycmF5W10gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hhbm5lbHMgPSB0aGlzLl9hdWRpb0J1ZmZlci5udW1iZXJPZkNoYW5uZWxzO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIGV4dHJhY3QgdGhlIGRhdGEgZnJvbSBlYWNoIGNoYW5uZWxcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgY2hhbm5lbElkeCA9IDA7IGNoYW5uZWxJZHggPCBjaGFubmVsczsgY2hhbm5lbElkeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhUG9pbnRzW2NoYW5uZWxJZHhdID0gdGhpcy5fYXVkaW9CdWZmZXIuZ2V0Q2hhbm5lbERhdGEoY2hhbm5lbElkeCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KGRhdGFQb2ludHMpO1xuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIGNsZWFudXAgYWZ0ZXIgb3Vyc2VsdmVzXG4gICAgICAgICAgICAgICAgICAgIGRhdGFQb2ludHMgPSBudWxsO1xuICAgICAgICAgICAgICAgIH0sIChlcnJvcikgPT4gb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpKTtcbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4gb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZ2V0V2F2ZWZvcm1Qb2ludHMoY2hhbm5lbHM6IEZsb2F0MzJBcnJheVtdID0gW10sIHNraXA6IG51bWJlciA9IDEwMDApOiBXYXZlZm9ybVBvaW50W10ge1xuXG4gICAgICAgIGNvbnN0IHdhdmVmb3JtOiBXYXZlZm9ybVBvaW50W10gPSBbXTtcbiAgICAgICAgY29uc3QgZHVyYXRpb24gPSBjaGFubmVscy5sZW5ndGggPiAwID8gY2hhbm5lbHNbMF0ubGVuZ3RoIDogMDtcblxuICAgICAgICAvLyBjb252ZXJ0IGVhY2ggY2hhbm5lbCBkYXRhIHRvIGEgc2VyaWVzIG9mIHdhdmVmb3JtIHBvaW50c1xuICAgICAgICBmb3IgKGxldCBpZHggPSAwOyBpZHggPCBkdXJhdGlvbjsgaWR4ICs9IHNraXApIHtcblxuICAgICAgICAgICAgLy8gZ2V0IGFsbCB0aGUgY2hhbm5lbCBkYXRhIGZvciBhIHNwZWNpZmljIHBvaW50XG4gICAgICAgICAgICBjb25zdCBwb2ludHMgPSBjaGFubmVscy5tYXAoY2hhbm5lbCA9PiBjaGFubmVsW2lkeF0pO1xuXG4gICAgICAgICAgICAvLyBmaW5kIHRoZSBtaW5pbXVtIHBvaW50IGFuZCBtYXhpbXVtIHBvaW50cyBhdCBlYWNoIHBvc2l0aW9uIGFjcm9zcyBhbGwgY2hhbm5lbHNcbiAgICAgICAgICAgIHdhdmVmb3JtLnB1c2goe1xuICAgICAgICAgICAgICAgIG1pbjogcG9pbnRzLnJlZHVjZSgocHJldmlvdXMsIGN1cnJlbnQpID0+IGN1cnJlbnQgPCBwcmV2aW91cyA/IGN1cnJlbnQgOiBwcmV2aW91cyksXG4gICAgICAgICAgICAgICAgbWF4OiBwb2ludHMucmVkdWNlKChwcmV2aW91cywgY3VycmVudCkgPT4gY3VycmVudCA+IHByZXZpb3VzID8gY3VycmVudCA6IHByZXZpb3VzKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gd2F2ZWZvcm07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRBdWRpb0J1ZmZlcihhcnJheUJ1ZmZlcjogQXJyYXlCdWZmZXIpOiBPYnNlcnZhYmxlPEF1ZGlvQnVmZmVyPiB7XG4gICAgICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZSgob2JzZXJ2ZXI6IE9ic2VydmVyPEF1ZGlvQnVmZmVyPikgPT4ge1xuICAgICAgICAgICAgdGhpcy5nZXRPZmZsaW5lQXVkaW9Db250ZXh0KCkuZGVjb2RlQXVkaW9EYXRhKGFycmF5QnVmZmVyLCAoYXVkaW9CdWZmZXI6IEF1ZGlvQnVmZmVyKSA9PiB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChhdWRpb0J1ZmZlcik7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4gb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRPZmZsaW5lQXVkaW9Db250ZXh0KCk6IE9mZmxpbmVBdWRpb0NvbnRleHQge1xuICAgICAgICByZXR1cm4gbmV3IE9mZmxpbmVBdWRpb0NvbnRleHQoMSwgMiwgdGhpcy5fYXVkaW9Db250ZXh0LnNhbXBsZVJhdGUgfHwgNDQxMDApO1xuICAgIH1cblxuICAgIHByaXZhdGUgY3JlYXRlQnVmZmVyU291cmNlKGF1ZGlvQnVmZmVyOiBBdWRpb0J1ZmZlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmRpc2Nvbm5lY3RTb3VyY2UoKTtcblxuICAgICAgICB0aGlzLl9hdWRpb0J1ZmZlciA9IGF1ZGlvQnVmZmVyO1xuICAgICAgICB0aGlzLl9hdWRpb0J1ZmZlclNvdXJjZSA9IHRoaXMuX2F1ZGlvQ29udGV4dC5jcmVhdGVCdWZmZXJTb3VyY2UoKTtcbiAgICAgICAgdGhpcy5fYXVkaW9CdWZmZXJTb3VyY2UuYnVmZmVyID0gdGhpcy5fYXVkaW9CdWZmZXI7XG4gICAgICAgIHRoaXMuX2F1ZGlvQnVmZmVyU291cmNlLmNvbm5lY3QodGhpcy5fYW5hbHlzZXJOb2RlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZVZvbHVtZU5vZGUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX2dhaW5Ob2RlID0gdGhpcy5fYXVkaW9Db250ZXh0LmNyZWF0ZUdhaW4oKTtcbiAgICAgICAgdGhpcy5fZ2Fpbk5vZGUuY29ubmVjdCh0aGlzLl9hdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuICAgIH1cblxuICAgIHByaXZhdGUgY3JlYXRlQW5hbHlzZXJOb2RlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9hbmFseXNlck5vZGUgPSB0aGlzLl9hdWRpb0NvbnRleHQuY3JlYXRlQW5hbHlzZXIoKTtcbiAgICAgICAgdGhpcy5fYW5hbHlzZXJOb2RlLmNvbm5lY3QodGhpcy5fZ2Fpbk5vZGUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZGlzY29ubmVjdFNvdXJjZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuX2F1ZGlvQnVmZmVyU291cmNlKSB7XG4gICAgICAgICAgICB0aGlzLl9hdWRpb0J1ZmZlclNvdXJjZS5kaXNjb25uZWN0KCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2F2ZWZvcm1Qb2ludCB7XG4gICAgbWluOiBudW1iZXI7XG4gICAgbWF4OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXVkaW9NZXRhZGF0YSB7XG4gICAgZmlsZW5hbWU6IHN0cmluZztcbiAgICBleHRlbnNpb246IHN0cmluZztcbiAgICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICAgIHNpemU6IG51bWJlcjtcbn1cbiJdfQ==