UNPKG

matrix-react-sdk

Version:
202 lines (196 loc) 29 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.MediaDeviceKindEnum = exports.MediaDeviceHandlerEvent = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _events = _interopRequireDefault(require("events")); var _logger = require("matrix-js-sdk/src/logger"); var _SettingsStore = _interopRequireDefault(require("./settings/SettingsStore")); var _SettingLevel = require("./settings/SettingLevel"); var _MatrixClientPeg = require("./MatrixClientPeg"); var _languageHandler = require("./languageHandler"); /* Copyright 2024 New Vector Ltd. Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com> Copyright 2017 Michael Telatynski <7t3chguy@gmail.com> SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ // XXX: MediaDeviceKind is a union type, so we make our own enum let MediaDeviceKindEnum = exports.MediaDeviceKindEnum = /*#__PURE__*/function (MediaDeviceKindEnum) { MediaDeviceKindEnum["AudioOutput"] = "audiooutput"; MediaDeviceKindEnum["AudioInput"] = "audioinput"; MediaDeviceKindEnum["VideoInput"] = "videoinput"; return MediaDeviceKindEnum; }({}); let MediaDeviceHandlerEvent = exports.MediaDeviceHandlerEvent = /*#__PURE__*/function (MediaDeviceHandlerEvent) { MediaDeviceHandlerEvent["AudioOutputChanged"] = "audio_output_changed"; return MediaDeviceHandlerEvent; }({}); class MediaDeviceHandler extends _events.default { static get instance() { if (!MediaDeviceHandler.internalInstance) { MediaDeviceHandler.internalInstance = new MediaDeviceHandler(); } return MediaDeviceHandler.internalInstance; } static async hasAnyLabeledDevices() { const devices = await navigator.mediaDevices.enumerateDevices(); return devices.some(d => Boolean(d.label)); } /** * Gets the available audio input/output and video input devices * from the browser: a thin wrapper around mediaDevices.enumerateDevices() * that also returns results by type of devices. Note that this requires * user media permissions and an active stream, otherwise you'll get blank * device labels. * * Once the Permissions API * (https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API) * is ready for primetime, it might help make this simpler. * * @return Promise<IMediaDevices> The available media devices */ static async getDevices() { try { const devices = await navigator.mediaDevices.enumerateDevices(); const output = { [MediaDeviceKindEnum.AudioOutput]: [], [MediaDeviceKindEnum.AudioInput]: [], [MediaDeviceKindEnum.VideoInput]: [] }; devices.forEach(device => output[device.kind].push(device)); return output; } catch (error) { _logger.logger.warn("Unable to refresh WebRTC Devices: ", error); } } /** * Retrieves devices from the SettingsStore and tells the js-sdk to use them */ static async loadDevices() { const audioDeviceId = _SettingsStore.default.getValue("webrtc_audioinput"); const videoDeviceId = _SettingsStore.default.getValue("webrtc_videoinput"); await _MatrixClientPeg.MatrixClientPeg.safeGet().getMediaHandler().setAudioInput(audioDeviceId); await _MatrixClientPeg.MatrixClientPeg.safeGet().getMediaHandler().setVideoInput(videoDeviceId); await MediaDeviceHandler.updateAudioSettings(); } static async updateAudioSettings() { await _MatrixClientPeg.MatrixClientPeg.safeGet().getMediaHandler().setAudioSettings({ autoGainControl: MediaDeviceHandler.getAudioAutoGainControl(), echoCancellation: MediaDeviceHandler.getAudioEchoCancellation(), noiseSuppression: MediaDeviceHandler.getAudioNoiseSuppression() }); } setAudioOutput(deviceId) { _SettingsStore.default.setValue("webrtc_audiooutput", null, _SettingLevel.SettingLevel.DEVICE, deviceId); this.emit(MediaDeviceHandlerEvent.AudioOutputChanged, deviceId); } /** * This will not change the device that a potential call uses. The call will * need to be ended and started again for this change to take effect * @param {string} deviceId */ async setAudioInput(deviceId) { _SettingsStore.default.setValue("webrtc_audioinput", null, _SettingLevel.SettingLevel.DEVICE, deviceId); return _MatrixClientPeg.MatrixClientPeg.safeGet().getMediaHandler().setAudioInput(deviceId); } /** * This will not change the device that a potential call uses. The call will * need to be ended and started again for this change to take effect * @param {string} deviceId */ async setVideoInput(deviceId) { _SettingsStore.default.setValue("webrtc_videoinput", null, _SettingLevel.SettingLevel.DEVICE, deviceId); return _MatrixClientPeg.MatrixClientPeg.safeGet().getMediaHandler().setVideoInput(deviceId); } async setDevice(deviceId, kind) { switch (kind) { case MediaDeviceKindEnum.AudioOutput: this.setAudioOutput(deviceId); break; case MediaDeviceKindEnum.AudioInput: await this.setAudioInput(deviceId); break; case MediaDeviceKindEnum.VideoInput: await this.setVideoInput(deviceId); break; } } static async setAudioAutoGainControl(value) { await _SettingsStore.default.setValue("webrtc_audio_autoGainControl", null, _SettingLevel.SettingLevel.DEVICE, value); await MediaDeviceHandler.updateAudioSettings(); } static async setAudioEchoCancellation(value) { await _SettingsStore.default.setValue("webrtc_audio_echoCancellation", null, _SettingLevel.SettingLevel.DEVICE, value); await MediaDeviceHandler.updateAudioSettings(); } static async setAudioNoiseSuppression(value) { await _SettingsStore.default.setValue("webrtc_audio_noiseSuppression", null, _SettingLevel.SettingLevel.DEVICE, value); await MediaDeviceHandler.updateAudioSettings(); } static getAudioOutput() { return _SettingsStore.default.getValueAt(_SettingLevel.SettingLevel.DEVICE, "webrtc_audiooutput"); } static getAudioInput() { return _SettingsStore.default.getValueAt(_SettingLevel.SettingLevel.DEVICE, "webrtc_audioinput"); } static getVideoInput() { return _SettingsStore.default.getValueAt(_SettingLevel.SettingLevel.DEVICE, "webrtc_videoinput"); } static getAudioAutoGainControl() { return _SettingsStore.default.getValue("webrtc_audio_autoGainControl"); } static getAudioEchoCancellation() { return _SettingsStore.default.getValue("webrtc_audio_echoCancellation"); } static getAudioNoiseSuppression() { return _SettingsStore.default.getValue("webrtc_audio_noiseSuppression"); } /** * Returns the current set deviceId for a device kind * @param {MediaDeviceKindEnum} kind of the device that will be returned * @returns {string} the deviceId */ static getDevice(kind) { switch (kind) { case MediaDeviceKindEnum.AudioOutput: return this.getAudioOutput(); case MediaDeviceKindEnum.AudioInput: return this.getAudioInput(); case MediaDeviceKindEnum.VideoInput: return this.getVideoInput(); } } static get startWithAudioMuted() { return _SettingsStore.default.getValue("audioInputMuted"); } static set startWithAudioMuted(value) { _SettingsStore.default.setValue("audioInputMuted", null, _SettingLevel.SettingLevel.DEVICE, value); } static get startWithVideoMuted() { return _SettingsStore.default.getValue("videoInputMuted"); } static set startWithVideoMuted(value) { _SettingsStore.default.setValue("videoInputMuted", null, _SettingLevel.SettingLevel.DEVICE, value); } } exports.default = MediaDeviceHandler; (0, _defineProperty2.default)(MediaDeviceHandler, "internalInstance", void 0); (0, _defineProperty2.default)(MediaDeviceHandler, "getDefaultDevice", devices => { // Note we're looking for a device with deviceId 'default' but adding a device // with deviceId == the empty string: this is because Chrome gives us a device // with deviceId 'default', so we're looking for this, not the one we are adding. if (!devices.some(i => i.deviceId === "default")) { devices.unshift({ deviceId: "", label: (0, _languageHandler._t)("voip|default_device") }); return ""; } else { return "default"; } }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZXZlbnRzIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfbG9nZ2VyIiwiX1NldHRpbmdzU3RvcmUiLCJfU2V0dGluZ0xldmVsIiwiX01hdHJpeENsaWVudFBlZyIsIl9sYW5ndWFnZUhhbmRsZXIiLCJNZWRpYURldmljZUtpbmRFbnVtIiwiZXhwb3J0cyIsIk1lZGlhRGV2aWNlSGFuZGxlckV2ZW50IiwiTWVkaWFEZXZpY2VIYW5kbGVyIiwiRXZlbnRFbWl0dGVyIiwiaW5zdGFuY2UiLCJpbnRlcm5hbEluc3RhbmNlIiwiaGFzQW55TGFiZWxlZERldmljZXMiLCJkZXZpY2VzIiwibmF2aWdhdG9yIiwibWVkaWFEZXZpY2VzIiwiZW51bWVyYXRlRGV2aWNlcyIsInNvbWUiLCJkIiwiQm9vbGVhbiIsImxhYmVsIiwiZ2V0RGV2aWNlcyIsIm91dHB1dCIsIkF1ZGlvT3V0cHV0IiwiQXVkaW9JbnB1dCIsIlZpZGVvSW5wdXQiLCJmb3JFYWNoIiwiZGV2aWNlIiwia2luZCIsInB1c2giLCJlcnJvciIsImxvZ2dlciIsIndhcm4iLCJsb2FkRGV2aWNlcyIsImF1ZGlvRGV2aWNlSWQiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJ2aWRlb0RldmljZUlkIiwiTWF0cml4Q2xpZW50UGVnIiwic2FmZUdldCIsImdldE1lZGlhSGFuZGxlciIsInNldEF1ZGlvSW5wdXQiLCJzZXRWaWRlb0lucHV0IiwidXBkYXRlQXVkaW9TZXR0aW5ncyIsInNldEF1ZGlvU2V0dGluZ3MiLCJhdXRvR2FpbkNvbnRyb2wiLCJnZXRBdWRpb0F1dG9HYWluQ29udHJvbCIsImVjaG9DYW5jZWxsYXRpb24iLCJnZXRBdWRpb0VjaG9DYW5jZWxsYXRpb24iLCJub2lzZVN1cHByZXNzaW9uIiwiZ2V0QXVkaW9Ob2lzZVN1cHByZXNzaW9uIiwic2V0QXVkaW9PdXRwdXQiLCJkZXZpY2VJZCIsInNldFZhbHVlIiwiU2V0dGluZ0xldmVsIiwiREVWSUNFIiwiZW1pdCIsIkF1ZGlvT3V0cHV0Q2hhbmdlZCIsInNldERldmljZSIsInNldEF1ZGlvQXV0b0dhaW5Db250cm9sIiwidmFsdWUiLCJzZXRBdWRpb0VjaG9DYW5jZWxsYXRpb24iLCJzZXRBdWRpb05vaXNlU3VwcHJlc3Npb24iLCJnZXRBdWRpb091dHB1dCIsImdldFZhbHVlQXQiLCJnZXRBdWRpb0lucHV0IiwiZ2V0VmlkZW9JbnB1dCIsImdldERldmljZSIsInN0YXJ0V2l0aEF1ZGlvTXV0ZWQiLCJzdGFydFdpdGhWaWRlb011dGVkIiwiZGVmYXVsdCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJpIiwidW5zaGlmdCIsIl90Il0sInNvdXJjZXMiOlsiLi4vc3JjL01lZGlhRGV2aWNlSGFuZGxlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAyMSDFoGltb24gQnJhbmRuZXIgPHNpbW9uLmJyYS5hZ0BnbWFpbC5jb20+XG5Db3B5cmlnaHQgMjAxNyBNaWNoYWVsIFRlbGF0eW5za2kgPDd0M2NoZ3V5QGdtYWlsLmNvbT5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IEV2ZW50RW1pdHRlciBmcm9tIFwiZXZlbnRzXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5cbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCB7IFNldHRpbmdMZXZlbCB9IGZyb20gXCIuL3NldHRpbmdzL1NldHRpbmdMZXZlbFwiO1xuaW1wb3J0IHsgTWF0cml4Q2xpZW50UGVnIH0gZnJvbSBcIi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgeyBfdCB9IGZyb20gXCIuL2xhbmd1YWdlSGFuZGxlclwiO1xuXG4vLyBYWFg6IE1lZGlhRGV2aWNlS2luZCBpcyBhIHVuaW9uIHR5cGUsIHNvIHdlIG1ha2Ugb3VyIG93biBlbnVtXG5leHBvcnQgZW51bSBNZWRpYURldmljZUtpbmRFbnVtIHtcbiAgICBBdWRpb091dHB1dCA9IFwiYXVkaW9vdXRwdXRcIixcbiAgICBBdWRpb0lucHV0ID0gXCJhdWRpb2lucHV0XCIsXG4gICAgVmlkZW9JbnB1dCA9IFwidmlkZW9pbnB1dFwiLFxufVxuXG5leHBvcnQgdHlwZSBJTWVkaWFEZXZpY2VzID0gUmVjb3JkPE1lZGlhRGV2aWNlS2luZEVudW0sIEFycmF5PE1lZGlhRGV2aWNlSW5mbz4+O1xuXG5leHBvcnQgZW51bSBNZWRpYURldmljZUhhbmRsZXJFdmVudCB7XG4gICAgQXVkaW9PdXRwdXRDaGFuZ2VkID0gXCJhdWRpb19vdXRwdXRfY2hhbmdlZFwiLFxufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNZWRpYURldmljZUhhbmRsZXIgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuICAgIHByaXZhdGUgc3RhdGljIGludGVybmFsSW5zdGFuY2U/OiBNZWRpYURldmljZUhhbmRsZXI7XG5cbiAgICBwdWJsaWMgc3RhdGljIGdldCBpbnN0YW5jZSgpOiBNZWRpYURldmljZUhhbmRsZXIge1xuICAgICAgICBpZiAoIU1lZGlhRGV2aWNlSGFuZGxlci5pbnRlcm5hbEluc3RhbmNlKSB7XG4gICAgICAgICAgICBNZWRpYURldmljZUhhbmRsZXIuaW50ZXJuYWxJbnN0YW5jZSA9IG5ldyBNZWRpYURldmljZUhhbmRsZXIoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gTWVkaWFEZXZpY2VIYW5kbGVyLmludGVybmFsSW5zdGFuY2U7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBhc3luYyBoYXNBbnlMYWJlbGVkRGV2aWNlcygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlcyA9IGF3YWl0IG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcygpO1xuICAgICAgICByZXR1cm4gZGV2aWNlcy5zb21lKChkKSA9PiBCb29sZWFuKGQubGFiZWwpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBhdmFpbGFibGUgYXVkaW8gaW5wdXQvb3V0cHV0IGFuZCB2aWRlbyBpbnB1dCBkZXZpY2VzXG4gICAgICogZnJvbSB0aGUgYnJvd3NlcjogYSB0aGluIHdyYXBwZXIgYXJvdW5kIG1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKClcbiAgICAgKiB0aGF0IGFsc28gcmV0dXJucyByZXN1bHRzIGJ5IHR5cGUgb2YgZGV2aWNlcy4gTm90ZSB0aGF0IHRoaXMgcmVxdWlyZXNcbiAgICAgKiB1c2VyIG1lZGlhIHBlcm1pc3Npb25zIGFuZCBhbiBhY3RpdmUgc3RyZWFtLCBvdGhlcndpc2UgeW91J2xsIGdldCBibGFua1xuICAgICAqIGRldmljZSBsYWJlbHMuXG4gICAgICpcbiAgICAgKiBPbmNlIHRoZSBQZXJtaXNzaW9ucyBBUElcbiAgICAgKiAoaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1Blcm1pc3Npb25zX0FQSSlcbiAgICAgKiBpcyByZWFkeSBmb3IgcHJpbWV0aW1lLCBpdCBtaWdodCBoZWxwIG1ha2UgdGhpcyBzaW1wbGVyLlxuICAgICAqXG4gICAgICogQHJldHVybiBQcm9taXNlPElNZWRpYURldmljZXM+IFRoZSBhdmFpbGFibGUgbWVkaWEgZGV2aWNlc1xuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgYXN5bmMgZ2V0RGV2aWNlcygpOiBQcm9taXNlPElNZWRpYURldmljZXMgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGRldmljZXMgPSBhd2FpdCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKTtcbiAgICAgICAgICAgIGNvbnN0IG91dHB1dDogUmVjb3JkPE1lZGlhRGV2aWNlS2luZEVudW0sIE1lZGlhRGV2aWNlSW5mb1tdPiA9IHtcbiAgICAgICAgICAgICAgICBbTWVkaWFEZXZpY2VLaW5kRW51bS5BdWRpb091dHB1dF06IFtdLFxuICAgICAgICAgICAgICAgIFtNZWRpYURldmljZUtpbmRFbnVtLkF1ZGlvSW5wdXRdOiBbXSxcbiAgICAgICAgICAgICAgICBbTWVkaWFEZXZpY2VLaW5kRW51bS5WaWRlb0lucHV0XTogW10sXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBkZXZpY2VzLmZvckVhY2goKGRldmljZSkgPT4gb3V0cHV0W2RldmljZS5raW5kXS5wdXNoKGRldmljZSkpO1xuICAgICAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiVW5hYmxlIHRvIHJlZnJlc2ggV2ViUlRDIERldmljZXM6IFwiLCBlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhdGljIGdldERlZmF1bHREZXZpY2UgPSAoZGV2aWNlczogQXJyYXk8UGFydGlhbDxNZWRpYURldmljZUluZm8+Pik6IHN0cmluZyA9PiB7XG4gICAgICAgIC8vIE5vdGUgd2UncmUgbG9va2luZyBmb3IgYSBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnZGVmYXVsdCcgYnV0IGFkZGluZyBhIGRldmljZVxuICAgICAgICAvLyB3aXRoIGRldmljZUlkID09IHRoZSBlbXB0eSBzdHJpbmc6IHRoaXMgaXMgYmVjYXVzZSBDaHJvbWUgZ2l2ZXMgdXMgYSBkZXZpY2VcbiAgICAgICAgLy8gd2l0aCBkZXZpY2VJZCAnZGVmYXVsdCcsIHNvIHdlJ3JlIGxvb2tpbmcgZm9yIHRoaXMsIG5vdCB0aGUgb25lIHdlIGFyZSBhZGRpbmcuXG4gICAgICAgIGlmICghZGV2aWNlcy5zb21lKChpKSA9PiBpLmRldmljZUlkID09PSBcImRlZmF1bHRcIikpIHtcbiAgICAgICAgICAgIGRldmljZXMudW5zaGlmdCh7IGRldmljZUlkOiBcIlwiLCBsYWJlbDogX3QoXCJ2b2lwfGRlZmF1bHRfZGV2aWNlXCIpIH0pO1xuICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gXCJkZWZhdWx0XCI7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGRldmljZXMgZnJvbSB0aGUgU2V0dGluZ3NTdG9yZSBhbmQgdGVsbHMgdGhlIGpzLXNkayB0byB1c2UgdGhlbVxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgYXN5bmMgbG9hZERldmljZXMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGF1ZGlvRGV2aWNlSWQgPSBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwid2VicnRjX2F1ZGlvaW5wdXRcIik7XG4gICAgICAgIGNvbnN0IHZpZGVvRGV2aWNlSWQgPSBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwid2VicnRjX3ZpZGVvaW5wdXRcIik7XG5cbiAgICAgICAgYXdhaXQgTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRNZWRpYUhhbmRsZXIoKS5zZXRBdWRpb0lucHV0KGF1ZGlvRGV2aWNlSWQpO1xuICAgICAgICBhd2FpdCBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmdldE1lZGlhSGFuZGxlcigpLnNldFZpZGVvSW5wdXQodmlkZW9EZXZpY2VJZCk7XG5cbiAgICAgICAgYXdhaXQgTWVkaWFEZXZpY2VIYW5kbGVyLnVwZGF0ZUF1ZGlvU2V0dGluZ3MoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBhc3luYyB1cGRhdGVBdWRpb1NldHRpbmdzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmdldE1lZGlhSGFuZGxlcigpLnNldEF1ZGlvU2V0dGluZ3Moe1xuICAgICAgICAgICAgYXV0b0dhaW5Db250cm9sOiBNZWRpYURldmljZUhhbmRsZXIuZ2V0QXVkaW9BdXRvR2FpbkNvbnRyb2woKSxcbiAgICAgICAgICAgIGVjaG9DYW5jZWxsYXRpb246IE1lZGlhRGV2aWNlSGFuZGxlci5nZXRBdWRpb0VjaG9DYW5jZWxsYXRpb24oKSxcbiAgICAgICAgICAgIG5vaXNlU3VwcHJlc3Npb246IE1lZGlhRGV2aWNlSGFuZGxlci5nZXRBdWRpb05vaXNlU3VwcHJlc3Npb24oKSxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldEF1ZGlvT3V0cHV0KGRldmljZUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgU2V0dGluZ3NTdG9yZS5zZXRWYWx1ZShcIndlYnJ0Y19hdWRpb291dHB1dFwiLCBudWxsLCBTZXR0aW5nTGV2ZWwuREVWSUNFLCBkZXZpY2VJZCk7XG4gICAgICAgIHRoaXMuZW1pdChNZWRpYURldmljZUhhbmRsZXJFdmVudC5BdWRpb091dHB1dENoYW5nZWQsIGRldmljZUlkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIHdpbGwgbm90IGNoYW5nZSB0aGUgZGV2aWNlIHRoYXQgYSBwb3RlbnRpYWwgY2FsbCB1c2VzLiBUaGUgY2FsbCB3aWxsXG4gICAgICogbmVlZCB0byBiZSBlbmRlZCBhbmQgc3RhcnRlZCBhZ2FpbiBmb3IgdGhpcyBjaGFuZ2UgdG8gdGFrZSBlZmZlY3RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZGV2aWNlSWRcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2V0QXVkaW9JbnB1dChkZXZpY2VJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIFNldHRpbmdzU3RvcmUuc2V0VmFsdWUoXCJ3ZWJydGNfYXVkaW9pbnB1dFwiLCBudWxsLCBTZXR0aW5nTGV2ZWwuREVWSUNFLCBkZXZpY2VJZCk7XG4gICAgICAgIHJldHVybiBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmdldE1lZGlhSGFuZGxlcigpLnNldEF1ZGlvSW5wdXQoZGV2aWNlSWQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgd2lsbCBub3QgY2hhbmdlIHRoZSBkZXZpY2UgdGhhdCBhIHBvdGVudGlhbCBjYWxsIHVzZXMuIFRoZSBjYWxsIHdpbGxcbiAgICAgKiBuZWVkIHRvIGJlIGVuZGVkIGFuZCBzdGFydGVkIGFnYWluIGZvciB0aGlzIGNoYW5nZSB0byB0YWtlIGVmZmVjdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBkZXZpY2VJZFxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZXRWaWRlb0lucHV0KGRldmljZUlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgU2V0dGluZ3NTdG9yZS5zZXRWYWx1ZShcIndlYnJ0Y192aWRlb2lucHV0XCIsIG51bGwsIFNldHRpbmdMZXZlbC5ERVZJQ0UsIGRldmljZUlkKTtcbiAgICAgICAgcmV0dXJuIE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkuZ2V0TWVkaWFIYW5kbGVyKCkuc2V0VmlkZW9JbnB1dChkZXZpY2VJZCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldERldmljZShkZXZpY2VJZDogc3RyaW5nLCBraW5kOiBNZWRpYURldmljZUtpbmRFbnVtKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHN3aXRjaCAoa2luZCkge1xuICAgICAgICAgICAgY2FzZSBNZWRpYURldmljZUtpbmRFbnVtLkF1ZGlvT3V0cHV0OlxuICAgICAgICAgICAgICAgIHRoaXMuc2V0QXVkaW9PdXRwdXQoZGV2aWNlSWQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBNZWRpYURldmljZUtpbmRFbnVtLkF1ZGlvSW5wdXQ6XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXRBdWRpb0lucHV0KGRldmljZUlkKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgTWVkaWFEZXZpY2VLaW5kRW51bS5WaWRlb0lucHV0OlxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2V0VmlkZW9JbnB1dChkZXZpY2VJZCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhdGljIGFzeW5jIHNldEF1ZGlvQXV0b0dhaW5Db250cm9sKHZhbHVlOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IFNldHRpbmdzU3RvcmUuc2V0VmFsdWUoXCJ3ZWJydGNfYXVkaW9fYXV0b0dhaW5Db250cm9sXCIsIG51bGwsIFNldHRpbmdMZXZlbC5ERVZJQ0UsIHZhbHVlKTtcbiAgICAgICAgYXdhaXQgTWVkaWFEZXZpY2VIYW5kbGVyLnVwZGF0ZUF1ZGlvU2V0dGluZ3MoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhdGljIGFzeW5jIHNldEF1ZGlvRWNob0NhbmNlbGxhdGlvbih2YWx1ZTogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCBTZXR0aW5nc1N0b3JlLnNldFZhbHVlKFwid2VicnRjX2F1ZGlvX2VjaG9DYW5jZWxsYXRpb25cIiwgbnVsbCwgU2V0dGluZ0xldmVsLkRFVklDRSwgdmFsdWUpO1xuICAgICAgICBhd2FpdCBNZWRpYURldmljZUhhbmRsZXIudXBkYXRlQXVkaW9TZXR0aW5ncygpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdGF0aWMgYXN5bmMgc2V0QXVkaW9Ob2lzZVN1cHByZXNzaW9uKHZhbHVlOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IFNldHRpbmdzU3RvcmUuc2V0VmFsdWUoXCJ3ZWJydGNfYXVkaW9fbm9pc2VTdXBwcmVzc2lvblwiLCBudWxsLCBTZXR0aW5nTGV2ZWwuREVWSUNFLCB2YWx1ZSk7XG4gICAgICAgIGF3YWl0IE1lZGlhRGV2aWNlSGFuZGxlci51cGRhdGVBdWRpb1NldHRpbmdzKCk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBnZXRBdWRpb091dHB1dCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZUF0KFNldHRpbmdMZXZlbC5ERVZJQ0UsIFwid2VicnRjX2F1ZGlvb3V0cHV0XCIpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdGF0aWMgZ2V0QXVkaW9JbnB1dCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZUF0KFNldHRpbmdMZXZlbC5ERVZJQ0UsIFwid2VicnRjX2F1ZGlvaW5wdXRcIik7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBnZXRWaWRlb0lucHV0KCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBTZXR0aW5nc1N0b3JlLmdldFZhbHVlQXQoU2V0dGluZ0xldmVsLkRFVklDRSwgXCJ3ZWJydGNfdmlkZW9pbnB1dFwiKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhdGljIGdldEF1ZGlvQXV0b0dhaW5Db250cm9sKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcIndlYnJ0Y19hdWRpb19hdXRvR2FpbkNvbnRyb2xcIik7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBnZXRBdWRpb0VjaG9DYW5jZWxsYXRpb24oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwid2VicnRjX2F1ZGlvX2VjaG9DYW5jZWxsYXRpb25cIik7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBnZXRBdWRpb05vaXNlU3VwcHJlc3Npb24oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwid2VicnRjX2F1ZGlvX25vaXNlU3VwcHJlc3Npb25cIik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY3VycmVudCBzZXQgZGV2aWNlSWQgZm9yIGEgZGV2aWNlIGtpbmRcbiAgICAgKiBAcGFyYW0ge01lZGlhRGV2aWNlS2luZEVudW19IGtpbmQgb2YgdGhlIGRldmljZSB0aGF0IHdpbGwgYmUgcmV0dXJuZWRcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSB0aGUgZGV2aWNlSWRcbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIGdldERldmljZShraW5kOiBNZWRpYURldmljZUtpbmRFbnVtKTogc3RyaW5nIHtcbiAgICAgICAgc3dpdGNoIChraW5kKSB7XG4gICAgICAgICAgICBjYXNlIE1lZGlhRGV2aWNlS2luZEVudW0uQXVkaW9PdXRwdXQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0QXVkaW9PdXRwdXQoKTtcbiAgICAgICAgICAgIGNhc2UgTWVkaWFEZXZpY2VLaW5kRW51bS5BdWRpb0lucHV0OlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEF1ZGlvSW5wdXQoKTtcbiAgICAgICAgICAgIGNhc2UgTWVkaWFEZXZpY2VLaW5kRW51bS5WaWRlb0lucHV0OlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldFZpZGVvSW5wdXQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBzdGF0aWMgZ2V0IHN0YXJ0V2l0aEF1ZGlvTXV0ZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwiYXVkaW9JbnB1dE11dGVkXCIpO1xuICAgIH1cbiAgICBwdWJsaWMgc3RhdGljIHNldCBzdGFydFdpdGhBdWRpb011dGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICAgIFNldHRpbmdzU3RvcmUuc2V0VmFsdWUoXCJhdWRpb0lucHV0TXV0ZWRcIiwgbnVsbCwgU2V0dGluZ0xldmVsLkRFVklDRSwgdmFsdWUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdGF0aWMgZ2V0IHN0YXJ0V2l0aFZpZGVvTXV0ZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwidmlkZW9JbnB1dE11dGVkXCIpO1xuICAgIH1cbiAgICBwdWJsaWMgc3RhdGljIHNldCBzdGFydFdpdGhWaWRlb011dGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICAgIFNldHRpbmdzU3RvcmUuc2V0VmFsdWUoXCJ2aWRlb0lucHV0TXV0ZWRcIiwgbnVsbCwgU2V0dGluZ0xldmVsLkRFVklDRSwgdmFsdWUpO1xuICAgIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQSxJQUFBQSxPQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFELE9BQUE7QUFFQSxJQUFBRSxjQUFBLEdBQUFILHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRyxhQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxnQkFBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssZ0JBQUEsR0FBQUwsT0FBQTtBQWZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFVQTtBQUFBLElBQ1lNLG1CQUFtQixHQUFBQyxPQUFBLENBQUFELG1CQUFBLDBCQUFuQkEsbUJBQW1CO0VBQW5CQSxtQkFBbUI7RUFBbkJBLG1CQUFtQjtFQUFuQkEsbUJBQW1CO0VBQUEsT0FBbkJBLG1CQUFtQjtBQUFBO0FBQUEsSUFRbkJFLHVCQUF1QixHQUFBRCxPQUFBLENBQUFDLHVCQUFBLDBCQUF2QkEsdUJBQXVCO0VBQXZCQSx1QkFBdUI7RUFBQSxPQUF2QkEsdUJBQXVCO0FBQUE7QUFJcEIsTUFBTUMsa0JBQWtCLFNBQVNDLGVBQVksQ0FBQztFQUd6RCxXQUFrQkMsUUFBUUEsQ0FBQSxFQUF1QjtJQUM3QyxJQUFJLENBQUNGLGtCQUFrQixDQUFDRyxnQkFBZ0IsRUFBRTtNQUN0Q0gsa0JBQWtCLENBQUNHLGdCQUFnQixHQUFHLElBQUlILGtCQUFrQixDQUFDLENBQUM7SUFDbEU7SUFDQSxPQUFPQSxrQkFBa0IsQ0FBQ0csZ0JBQWdCO0VBQzlDO0VBRUEsYUFBb0JDLG9CQUFvQkEsQ0FBQSxFQUFxQjtJQUN6RCxNQUFN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