speaker-calibration 2.2.219 → 2.2.220
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/dist/example/i18n.js +4013 -3780
- package/dist/listener.js +411 -4
- package/dist/main.js +1 -1
- package/package.json +1 -1
- package/src/listener-app/listener.js +34 -41
- package/src/peer-connection/audioPeer.js +4 -39
- package/src/peer-connection/listener.js +86 -8
package/dist/main.js
CHANGED
|
@@ -103,7 +103,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core
|
|
|
103
103
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
104
104
|
|
|
105
105
|
"use strict";
|
|
106
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.object.from-entries.js */ \"./node_modules/core-js/modules/es.object.from-entries.js\");\n/* harmony import */ var core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/web.url-search-params.js */ \"./node_modules/core-js/modules/web.url-search-params.js\");\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var peerjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! peerjs */ \"./node_modules/peerjs/dist/bundler.mjs\");\n\n\n\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n// TODO: this was already here before, but appears to be unused\nconst pressFeedbackURI = 'data:audio/mpeg;base64,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VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//uSZIIP9BFGHYksMlIAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==';\n\n/**\r\n * @typedef initParameters - Parameters for initializing the AudioPeer\r\n * @type {object}\r\n * @property {string} targetElementId - Target element where new elements will be appended.\r\n * @property {string} siteUrl: The url of the current site.\r\n */\nconst initParameters = {\n targetElementId: null,\n siteUrl: null\n};\n\n/**\r\n * @class The first layer of abstraction on the PeerJS library.\r\n * It meant to be extended by the two seperate client classes, Speaker and Listener.\r\n * It implements the shared methods and properties of both classes.\r\n */\nclass AudioPeer {\n /**\r\n * Creates an instance of AudioPeer\r\n * Takes the url of the current site and a target element where html elements will be appended.\r\n *\r\n * @param params - See type definition for initParameters.\r\n * @param param\r\n * @example\r\n */\n constructor() {\n var _this = this;\n let param = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initParameters;\n /** .\r\n * .\r\n * .\r\n * Helper method to display information to DOM element\r\n *\r\n * @param {string} message\r\n * @param {boolean} append\r\n * @example\r\n */\n _defineProperty(this, \"displayUpdate\", function (message) {\n let append = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n // If the specified elem exists, update that elem\n if (document.getElementById(_this.targetElement)) {\n const displayElement = document.getElementById(_this.targetElement);\n if (append) {\n displayElement.innerText += \"\\n\".concat(message);\n } else {\n displayElement.innerText = message;\n }\n } else {\n console.log('MESSAGE: ', message);\n }\n });\n /**\r\n * Callback method for when a peer connection is lost\r\n * saves the last peer id, last server id, and attempts to reconnect.\r\n *\r\n * @example\r\n */\n _defineProperty(this, \"onPeerDisconnected\", () => {\n this.displayUpdate('Connection lost. Please reconnect');\n\n // Workaround for peer.reconnect deleting previous id\n try {\n this.peer.id = this.lastPeerId;\n // eslint-disable-next-line no-underscore-dangle\n this.peer._lastServerId = this.lastPeerId;\n this.peer.reconnect();\n } catch (e) {\n console.log(e);\n }\n });\n /** .\r\n * .\r\n * .\r\n * Callback method that cleans up after peer connection is closed\r\n *\r\n * @example\r\n */\n _defineProperty(this, \"onPeerClose\", () => {\n this.displayUpdate('Connection closed');\n this.conn = null;\n });\n /** .\r\n * .\r\n * .\r\n * Helper method for when an error occurs\r\n *\r\n * @param {*} err\r\n * @example\r\n */\n _defineProperty(this, \"onPeerError\", err => {\n this.displayUpdate(err);\n console.log(\"\".concat(err));\n });\n /** .\r\n * .\r\n * .\r\n * Helper method that converts url paramters to an object\r\n *\r\n * @returns {object}\r\n * @example\r\n */\n _defineProperty(this, \"parseURLSearchParams\", () =>\n // SOURCE: chickens, https://stackoverflow.com/questions/8648892/how-to-convert-url-parameters-to-a-javascript-object\n // eslint-disable-next-line no-restricted-globals\n Object.fromEntries(new URLSearchParams(location.search)));\n /** .\r\n * .\r\n * .\r\n * Helper method that converts an object to a query string\r\n *\r\n * @param {object} params\r\n * @returns {string}\r\n * @example\r\n */\n _defineProperty(this, \"queryStringFromObject\", params => Object.keys(params).map(key => \"\".concat(key, \"=\").concat(params[key])).join('&'));\n // PeerJS\n /* Create the Peer object for our end of the connection. */\n this.peer = new peerjs__WEBPACK_IMPORTED_MODULE_3__[\"default\"]({\n secure: true,\n host: 'easyeyes-peer-server.herokuapp.com',\n port: 443,\n config: {\n iceServers: [{\n urls: 'stun:stun.relay.metered.ca:80'\n }, {\n urls: 'turn:global.relay.metered.ca:80',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }, {\n urls: 'turn:global.relay.metered.ca:80?transport=tcp',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }, {\n urls: 'turn:global.relay.metered.ca:443',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }, {\n urls: 'turns:global.relay.metered.ca:443?transport=tcp',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }]\n }\n });\n this.conn = null;\n this.lastPeerId = null;\n\n // Display information to HTML elem with given id\n this.targetElement = param.targetElementId;\n this.siteUrl = param.siteUrl;\n this.debug = false;\n // Store for all incoming data\n this.dataStore = [];\n\n // Create and play sounds using this audio context\n this.sourceAudioContext = new (window.AudioContext || window.webkitAudioContext || window.audioContext)();\n }\n}\n_defineProperty(AudioPeer, \"keypressFeedbackSound\", pressFeedbackURI);\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioPeer);\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/audioPeer.js?");
|
|
106
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.object.from-entries.js */ \"./node_modules/core-js/modules/es.object.from-entries.js\");\n/* harmony import */ var core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/web.url-search-params.js */ \"./node_modules/core-js/modules/web.url-search-params.js\");\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2__);\n\n\n\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n// TODO: this was already here before, but appears to be unused\nconst pressFeedbackURI = 'data:audio/mpeg;base64,//uQZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAALAAATlgAXFxcXFxcXFxcuLi4uLi4uLi5FRUVFRUVFRUVdXV1dXV1dXV10dHR0dHR0dHSLi4uLi4uLi4uioqKioqKioqK6urq6urq6urrR0dHR0dHR0dHo6Ojo6Ojo6Oj///////////8AAAA5TEFNRTMuMTAwAaoAAAAALgYAABSAJAZbTgAAgAAAE5YfafL/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//uQZAAAA0YVyhVvQAAAAA0goAABGfWdITn6gAgAADSDAAAAAEWjAwMwMDMFBzCQsw8PMPCwUDgkNMpNzXEoSUTP3s6nJPd4z28k62JNdIwIUHj3nvynRempMmLAo/tff9/3IchyHIch/IxY3SUmG86enD4Pg+fgmfEAIQQcsP+oH//E7/+Ud/1HP/B9AAABMCFFFAAAwDgCyMCVAgQcBQmARAHw0AOGAUgFJgUoL8YKsEvqzGA1APJQAIGBNgDpoBRvQYb6EIGhIkmJg1QA0aH0H4GDBgJ4G55UBpM1AGgUG0wAgOBIUAYJGoGFQ4AkHitxzRSocGMwDYYCwJAWAICgBD8jhwlEqBNsMiAkCBpQY2FxpG61opmucDLrjKi6Fmk5oK9PWVh1DNFM2IaRH/q8mTQgTF4sk0bnv//zEuqRMjYycuuj///5wxZzIvLSMTUxYyZL////86ZBqh4D+QUIABcwBQBLMCmAeTA4wJowO8E2DAeYwQ8CWMDLBHDB1QpIxscoSMwBQJj/WZBA3O4mFMHIAGzAKAVgwmcG8OIV//uSZCIN9VQ4wgd/gAAAAA0g4AABD+S/Di5+qgAAADSAAAAEEzcNTC4yM0m41SLDHAJLSggBKwtKRwb6+IBi4ctbepDskh2KmAgA16NTNrON66ptO40mNa9ayZHVx7zmGPHktZb7vP9xLn4fr+9jeO//8P+z39///9T/////t+d6vf1+c6fP9Hv5cxg4aA4TgkGIYmLbYHGAxaCjHwlM0lwBC4zGwzVG+MFnGoTY8sn0w1MSHA09vAM8ssDCSYAykIABmeCI4AKDMDIRfGbFAjWE8h+BfIEfBoFCTQJUcA5ZIrQDjzQ+gWzxsjDLtE4s46kxjHZZom2SXfyj6uadvNvb0ee/3dX//01YAVKw/FoW3hDrwUDTAwDMVigy8rTYaRNKug2tzzBwxnAx/DOuMhFECAOxWsDO6kAwkdQFH0BiwIgYlAwCgdAwiZBBI1kCC5JcWwCQWMQ/JQnkVFkOVN8oku8yDkjbMiry+2rrLvW/MvT53q/yv+n2///dywQL8DRgOgsrBBi0LGcngZrCZgYxGEAoZ+IplUdGJ1ifHVRh5v/7kmRMDPOhJ0MTn6qAAAANIAAAARDEiQhOf0pAAAA0gAAABAdCcEnCwmbqA1JhbIFwYKEAUGAXgOJo45oXAyjT0MinMgXM2UNoNGyYeLN0ENORMgQC5EYAJlr4Z3L3lgaHG5VO0lWX1q92J3t9sWM+bu9/fe8/VT/L+zq9v+zr9/+//8r71SAAAA9tq0AA1hzXXdxmzgPWzJyU20wh4EDDUSzWI4x4rgMGBd+IImDoAiEBAMCJn2HpqAlRpDIZhbxxp2ASQcGVRJG6RC4xmaZHiYlYPKGGdEGJjIoa4YtICXGHRhGJg2QMkYJADRGfCMTZE5+4ze1gMF1k163DfQrNgh83G3zIYoMdC4wEOwcrzMxMMam0AlYxkKzOgqMDhUuUBgYIQOWiEgwYHAogAwXBAYHAKAVVm0ZW2J1Wno9taaAzuOSF34AjMUjdBOy+pjbpKCil9TG/hOWRkUkxad2pAAAGFlrIADgyUqh1syPqzGQRoUAEDDoFgKMDw7MVA2NJ1sKHaMVghBwfGAgOgJR0migMTBUODDQezBI5jGNQzXD/+5JkjYD20jDN67/kngAADSAAAAEXjN0dTv9SAAAANIAAAASwgEb7HKvHZpiFAM0Bgs8wPYBNNi8MMfMIKRGRlOETOErM6wMGpBTQHTjJEQaKEBoKmlLXGizd5Ax5W2Byh0X6R9YRJ2rQFSKzgZDB0DQDKJHDr/MoZRDsaleN+vVhpoVqzczvZYx+Hdbx1/MuWOZb///Vr1YX93I/6P9KAWAQE8pFZWkOCuFAO0EEAThJ4OYwBQMHIJgUUVrHHRwaURUkZ4YX6MYvO6EDvpgTJY6aVeR7mGcgzBgfQE2YCuA5H9adJQKBCAhAqA53/aS/bk0T1zjIhpmcjVumpqS/ZZ1v6TuOXxF1+49x5d5Knl/Luvw7ua/8P/DdWT+dOkhD5zhvqb0db/93/5AQAQsF3glyO4MAysKti2BGAAdE0L31C4EMAhEAgAu28hgMOFHwEgaYACAFHpko0GM0ia2Yx0/wmKECIhpq5poYK2CTmAQAMhgAQBKYAoARFUAhUQbKhIMAxAFG3eFpLns4drJbaY9+pDVDPZ/QKtLHKNCpsTA6//uSZIEE9GAuRhNfzIAAAA0gAAABEnjLFK588sAAADSAAAAEdTXMSKxfop3DPM5RNbal/EvU7p6/Ie/t93Z1v6OqEAzmEmBoIQcGTCwGMCghPwvOQgUwEbKMZBgNAwOPZioUiMIl/ACXRGoREDB0clmTLApMiq4x2azRlmMM7NijivBEQxUIGvMGdAsjAxgHcDSxgRZANSYAOAgYs0FXAnwaIl43xAcuEVEogHIiFKRHEuREzUfFfSOoEgRyTk8Isema00Fl0gzqujqL/ZT3Krfoq7r1H/AvWzp/yXv/3f/oA0GjFwIZS19BgKAsiCDxuUBAMZ8D6zIZAIFMChweF7GFbQAITYoiSSSvMRBoUJ5l4RGVzOa2hhmAr6mbNSaYcYlxgqAvmAaCEYDAE6yBgAFIpAsGADyaXw+/MSnONGVBjhuNW+/dbYnEQqJJNwIgainmo0TB3Ofkus/yHs5P3dnW/+ryf+QqTEFNRTMuMTAwqqqqqqqqqqqqAABjBgrdYuwIwHSioNCCFkYbBZpMaoVDIRMDhB326ByJkJgYuGdC4P/7kmSwDPT4N0MLn6SAAAANIAAAARDIpRJOePLAAAA0gAAABDAGIA0YOGJhoVGKx+YbQxu2mmHbCT5rII6wYW2ASgYFJDgHYBAIpMARM6WcpEFALUjnWoXbkbwf8AGkx+2FugJGw/l2gIK+vverzfFet8Re/kur09f/f/u6f/1GySAhOMFigxOOnJAAdLIIqmTCCa9ahACTDANMqFMLAIQjQw0EVbjH4aOuN8OAgFCBn0sS0GpU0IAjUJ3MCoPaDTTB4AwnIE7MGrBCjAcgE836g5kUx6AtCKkjKElvKarxnFzLOlKRocalMtnabKM6hpYW5TSrdLe1Kop3e+ZWtymHt445fv9Vfyy/Hn5Xv///v1bXt4M9Z7+o729b+K/4b6pMQU1FMy4xMDCqqqqqqqqqqqoAArJ2QY8DbERAFjDyZMdBUwYDwIEDHduP9KsmPhhMKGHR0ZzTg0NTB4kGhkYqgZ2MZGQRUYNHoGXBgA4HWYEoBbGCNgvJhVgV8ZJaR2GsQJb5g5gRMYD+BQmAhADQNAVRoA4EQAOXUBwAkYBsAVr/+5Jk0w/0GynDE59coAAADSAAAAEULMkADn9SAAAANIAAAATsdabY4ta/VUMV5DuqzWuVs3pSSLmoKyJqFQGpUi+IAy2PdQm57ZU/m8oR6dDu/KvzehHpx5O/KkuvNN/o39SX9fblC3lusxd7wMr2zmhS+YLExsQBmRRQGKE6HITacxM2hgy8ATH50NVDsxSlQMPDL4bNJAg7HUAIBQcOjCRbMBtAdDAAACkwB4EWMCzCGTGll+U7EVMUMoPCSjDHgWcwaECqP+mza0I1QpATkY0Sm3lwsB0q0C3xd6GWuF4jEAeiqacWb5bdVxJbap8YzlnZWta3hLq34RaGf5hj3/pZ3HveY/3ku7/5a/7Wf//9/92aGoPcO9Z3nep/9H+mTEFNRTMuMTAwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgBOZ2IMSwdMDATGQhDC4ZXKRj8wGMxub0k5717G//uSZPaO9axfvJOfPEAAAA0gAAABFsja3g5/cEAAADSAAAAELQSBSmZKFYVCYsIjBA1MCgYxWdDkBzMRAEwgQDIIBMgFIzWQTUjgPK3c02lpDWsiqM0Ih0w6QzjB4BzMDcD4wFgEzAfAeQQs8TcsNydp+n5wlq8UapFM2auMpwfZrv475ll25Y5ll3mtzMuwCWO8Ocqe/lndv+j/b1f6/9QATU2x0wCPIAYTCoUHAxhIYX2MXBDC24mvTCAedLotPVa09tEZwuBrSZmkoXXBgkY2SmmPBjQkpGrwfaYZQGhQDcPACJNPw90xLlijCVZWUifsophFk7ww7v7fGk6gE/vB+l0VNkSFwo0bYXJC6gyQQEiwvlDzbHAhHpZLIQbJ1UxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVUASWNHVvyNdkdcuCnNLhmA8HuRIHbo/1AhfJ9JZVctla8gMQwpDT96eCGcDAGg8qCCIBce3D8P35RGMZXL8gcmxBByacE9hDD09hNohydtFshlp7EeIe9aMiMe/P/7kmTNjPTPJLaLvPDwAAANIAAAAQ/obuBt+FJAAAA0gAAABEchD3bEIchgekEBmZYRmyPAM3j4DJ8fhgfmeIjtD4HTwPAiPgNGB+BAAjtCABG8AwMvgwAEo5cSIfzt69YYDMdo9RxSsKtgIcom1PMylIK9rWkMkKzctAIIkqXCTqLYAoUrBCJrAlHzJipaMuaPvWraLnsMj6ExUtGUZ0ZRnJ7Q6PrnS7VrsC55kSlRyTYjonPkkybMT2AyVMrbMrYly661bq13Fz0K2JlbEdH1zk9ocnsB09CcutLYmj71p7Q6PWDI+hMXWjJ06Mozk9odH0BkfQmLrRlGdE6M5JrhKJzZKPoSSephKVHJlGcmLhkZXJJ9CYnrRkqSmMZybKpMQU1FMy4xMDCqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+5Jk7QT0dTc4kxw0ogAADSAAAAEZOaLm5+WQSAAANIAAAASqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqglFJEIRoPjA2MDYyViqViCJxDHghjyPQ4ioUiYKw4EMzYZXAooDEE1y2zRpTu00acWUWWcacaUWYeWcacJAhYgWJFCRQGIFiBZZRZRZlw7s7PG////s7M7Ozs7M5xpRZR5RRpxZRZh5RRZRbRC1NP///9PKqqq4NNNNRKqJXTTTTVVVTEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//uSZIIP9BFGHYksMlIAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==';\n\n/**\r\n * @typedef initParameters - Parameters for initializing the AudioPeer\r\n * @type {object}\r\n * @property {string} targetElementId - Target element where new elements will be appended.\r\n * @property {string} siteUrl: The url of the current site.\r\n */\nconst initParameters = {\n targetElementId: null,\n siteUrl: null\n};\n\n/**\r\n * @class The first layer of abstraction on the PeerJS library.\r\n * It meant to be extended by the two seperate client classes, Speaker and Listener.\r\n * It implements the shared methods and properties of both classes.\r\n */\nclass AudioPeer {\n /**\r\n * Creates an instance of AudioPeer\r\n * Takes the url of the current site and a target element where html elements will be appended.\r\n *\r\n * @param params - See type definition for initParameters.\r\n * @param param\r\n * @example\r\n */\n constructor() {\n var _this = this;\n let param = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initParameters;\n /** .\r\n * .\r\n * .\r\n * Helper method to display information to DOM element\r\n *\r\n * @param {string} message\r\n * @param {boolean} append\r\n * @example\r\n */\n _defineProperty(this, \"displayUpdate\", function (message) {\n let append = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n // If the specified elem exists, update that elem\n if (document.getElementById(_this.targetElement)) {\n const displayElement = document.getElementById(_this.targetElement);\n if (append) {\n displayElement.innerText += \"\\n\".concat(message);\n } else {\n displayElement.innerText = message;\n }\n } else {\n console.log('MESSAGE: ', message);\n }\n });\n /**\r\n * Callback method for when a peer connection is lost\r\n * saves the last peer id, last server id, and attempts to reconnect.\r\n *\r\n * @example\r\n */\n _defineProperty(this, \"onPeerDisconnected\", () => {\n this.displayUpdate('Connection lost. Please reconnect');\n\n // Workaround for peer.reconnect deleting previous id\n try {\n this.peer.id = this.lastPeerId;\n // eslint-disable-next-line no-underscore-dangle\n this.peer._lastServerId = this.lastPeerId;\n this.peer.reconnect();\n } catch (e) {\n console.log(e);\n }\n });\n /** .\r\n * .\r\n * .\r\n * Callback method that cleans up after peer connection is closed\r\n *\r\n * @example\r\n */\n _defineProperty(this, \"onPeerClose\", () => {\n this.displayUpdate('Connection closed');\n this.conn = null;\n });\n /** .\r\n * .\r\n * .\r\n * Helper method for when an error occurs\r\n *\r\n * @param {*} err\r\n * @example\r\n */\n _defineProperty(this, \"onPeerError\", err => {\n this.displayUpdate(err);\n console.log(\"\".concat(err));\n });\n /** .\r\n * .\r\n * .\r\n * Helper method that converts url paramters to an object\r\n *\r\n * @returns {object}\r\n * @example\r\n */\n _defineProperty(this, \"parseURLSearchParams\", () =>\n // SOURCE: chickens, https://stackoverflow.com/questions/8648892/how-to-convert-url-parameters-to-a-javascript-object\n // eslint-disable-next-line no-restricted-globals\n Object.fromEntries(new URLSearchParams(location.search)));\n /** .\r\n * .\r\n * .\r\n * Helper method that converts an object to a query string\r\n *\r\n * @param {object} params\r\n * @returns {string}\r\n * @example\r\n */\n _defineProperty(this, \"queryStringFromObject\", params => Object.keys(params).map(key => \"\".concat(key, \"=\").concat(params[key])).join('&'));\n this.conn = null;\n this.lastPeerId = null;\n\n // Display information to HTML elem with given id\n this.targetElement = param.targetElementId;\n this.siteUrl = param.siteUrl;\n this.debug = false;\n // Store for all incoming data\n this.dataStore = [];\n\n // Create and play sounds using this audio context\n this.sourceAudioContext = new (window.AudioContext || window.webkitAudioContext || window.audioContext)();\n }\n}\n_defineProperty(AudioPeer, \"keypressFeedbackSound\", pressFeedbackURI);\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioPeer);\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/audioPeer.js?");
|
|
107
107
|
|
|
108
108
|
/***/ }),
|
|
109
109
|
|
package/package.json
CHANGED
|
@@ -31,58 +31,51 @@ switch (isSmartPhone) {
|
|
|
31
31
|
// Initialize Listener early
|
|
32
32
|
const initializeListener = async () => {
|
|
33
33
|
window.listener = new Listener(listenerParameters);
|
|
34
|
+
await window.listener.initializePeer();
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
// Check microphone permission first
|
|
37
38
|
async function checkAndRequestMicrophonePermission() {
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
// Show permission request message
|
|
40
|
+
allowMicrophoneElement.innerText = phrases.RC_microphonePermission['en-US'];
|
|
41
|
+
container.style.display = 'block';
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
// Function to request microphone access
|
|
44
|
+
async function requestMicAccess(attempt = 1) {
|
|
45
|
+
try {
|
|
46
|
+
await navigator.mediaDevices.getUserMedia({audio: true});
|
|
47
|
+
// Permission granted, proceed to normal flow
|
|
43
48
|
initializeSmartPhoneDisplay();
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
await navigator.mediaDevices.getUserMedia({audio: true});
|
|
55
|
-
// Permission granted, proceed to normal flow
|
|
56
|
-
initializeSmartPhoneDisplay();
|
|
57
|
-
} catch (err) {
|
|
58
|
-
if (err.name === 'NotAllowedError') {
|
|
59
|
-
console.log('Permission explicitly denied');
|
|
60
|
-
// Permission explicitly denied
|
|
61
|
-
allowMicrophoneElement.innerText = phrases.RC_microphonePermissionDenied['en-US'];
|
|
62
|
-
// Send denied status and end study
|
|
63
|
-
let error = JSON.stringify(err);
|
|
64
|
-
await window.listener.sendPermissionStatus({type: 'denied', error: error});
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
49
|
+
} catch (err) {
|
|
50
|
+
if (err.name === 'NotAllowedError') {
|
|
51
|
+
console.log('Permission explicitly denied');
|
|
52
|
+
// Permission explicitly denied
|
|
53
|
+
allowMicrophoneElement.innerText = phrases.RC_microphonePermissionDenied['en-US'];
|
|
54
|
+
// Send denied status and end study
|
|
55
|
+
let error = JSON.stringify(err);
|
|
56
|
+
await window.listener.sendPermissionStatus({type: 'denied', error: error});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
67
59
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
60
|
+
// If 10 seconds passed, try again
|
|
61
|
+
if (attempt < 3) {
|
|
62
|
+
console.log('Retrying microphone access');
|
|
63
|
+
// Limit retries
|
|
64
|
+
setTimeout(() => requestMicAccess(attempt + 1), 10000);
|
|
65
|
+
} else {
|
|
66
|
+
console.log('All retries failed, treating as denied');
|
|
67
|
+
// After all retries failed, treat as denied
|
|
68
|
+
allowMicrophoneElement.innerText = phrases.RC_microphonePermissionDenied['en-US'];
|
|
69
|
+
let error = JSON.stringify(err);
|
|
70
|
+
await window.listener.sendPermissionStatus({type: 'error', error: error});
|
|
80
71
|
}
|
|
81
72
|
}
|
|
73
|
+
}
|
|
82
74
|
|
|
83
|
-
|
|
75
|
+
try {
|
|
76
|
+
await requestMicAccess();
|
|
84
77
|
} catch (err) {
|
|
85
|
-
console.error('Error
|
|
78
|
+
console.error('Error requesting microphone permission:', err);
|
|
86
79
|
allowMicrophoneElement.innerText = phrases.RC_microphonePermissionDenied['en-US'];
|
|
87
80
|
let error = JSON.stringify(err);
|
|
88
81
|
await window.listener.sendPermissionStatus({type: 'error', error: error});
|
|
@@ -30,40 +30,6 @@ class AudioPeer {
|
|
|
30
30
|
* @example
|
|
31
31
|
*/
|
|
32
32
|
constructor(param = initParameters) {
|
|
33
|
-
// PeerJS
|
|
34
|
-
/* Create the Peer object for our end of the connection. */
|
|
35
|
-
this.peer = new Peer({
|
|
36
|
-
secure: true,
|
|
37
|
-
host: 'easyeyes-peer-server.herokuapp.com',
|
|
38
|
-
port: 443,
|
|
39
|
-
config: {
|
|
40
|
-
iceServers: [
|
|
41
|
-
{
|
|
42
|
-
urls: 'stun:stun.relay.metered.ca:80',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
urls: 'turn:global.relay.metered.ca:80',
|
|
46
|
-
username: 'de884cfc34189cdf1a5dd616',
|
|
47
|
-
credential: 'IcOpouU9/TYBmpHU',
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
urls: 'turn:global.relay.metered.ca:80?transport=tcp',
|
|
51
|
-
username: 'de884cfc34189cdf1a5dd616',
|
|
52
|
-
credential: 'IcOpouU9/TYBmpHU',
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
urls: 'turn:global.relay.metered.ca:443',
|
|
56
|
-
username: 'de884cfc34189cdf1a5dd616',
|
|
57
|
-
credential: 'IcOpouU9/TYBmpHU',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
urls: 'turns:global.relay.metered.ca:443?transport=tcp',
|
|
61
|
-
username: 'de884cfc34189cdf1a5dd616',
|
|
62
|
-
credential: 'IcOpouU9/TYBmpHU',
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
33
|
this.conn = null;
|
|
68
34
|
this.lastPeerId = null;
|
|
69
35
|
|
|
@@ -116,13 +82,12 @@ class AudioPeer {
|
|
|
116
82
|
// Workaround for peer.reconnect deleting previous id
|
|
117
83
|
try {
|
|
118
84
|
this.peer.id = this.lastPeerId;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
} catch(e) {
|
|
85
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
86
|
+
this.peer._lastServerId = this.lastPeerId;
|
|
87
|
+
this.peer.reconnect();
|
|
88
|
+
} catch (e) {
|
|
123
89
|
console.log(e);
|
|
124
90
|
}
|
|
125
|
-
|
|
126
91
|
};
|
|
127
92
|
|
|
128
93
|
/** .
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import AudioPeer from './audioPeer';
|
|
2
2
|
import {UnsupportedDeviceError, MissingSpeakerIdError} from './peerErrors';
|
|
3
3
|
import axios from 'axios';
|
|
4
|
+
import Peer from 'peerjs';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @class Handles the listener's side of the connection. Responsible for getting access to user's microphone,
|
|
@@ -16,6 +17,7 @@ class Listener extends AudioPeer {
|
|
|
16
17
|
*/
|
|
17
18
|
constructor(params) {
|
|
18
19
|
super(params);
|
|
20
|
+
console.log('Listener constructor', this.peer);
|
|
19
21
|
this.microphoneFromAPI = params.microphoneFromAPI ? params.microphoneFromAPI : '';
|
|
20
22
|
this.microphoneDeviceId = params.microphoneDeviceId ? params.microphoneDeviceId : '';
|
|
21
23
|
// this.deviceInfoFromUser = params.deviceInfoFromUser
|
|
@@ -32,17 +34,92 @@ class Listener extends AudioPeer {
|
|
|
32
34
|
// previous calibrateSoundSamplingDesiredBits
|
|
33
35
|
urlParameters.bits !== null && urlParameters.bits !== undefined ? urlParameters.bits : 24;
|
|
34
36
|
this.speakerPeerId = urlParameters.speakerPeerId;
|
|
37
|
+
this.lastPeerId = this.speakerPeerId;
|
|
35
38
|
this.connOpen = false;
|
|
36
|
-
|
|
37
|
-
this.peer.on('open', this.onPeerOpen);
|
|
38
|
-
this.peer.on('connection', this.onPeerConnection);
|
|
39
|
-
this.peer.on('disconnected', this.onPeerDisconnected);
|
|
40
|
-
this.peer.on('close', this.onPeerClose);
|
|
41
|
-
this.peer.on('error', this.onPeerError);
|
|
42
39
|
}
|
|
40
|
+
generateTimeBasedPeerID = async () => {
|
|
41
|
+
const now = new Date().getTime();
|
|
42
|
+
const randomBuffer = new Uint8Array(10);
|
|
43
|
+
crypto.getRandomValues(randomBuffer);
|
|
44
|
+
const randomPart = Array.from(randomBuffer)
|
|
45
|
+
.map(b => b.toString(36))
|
|
46
|
+
.join('');
|
|
47
|
+
const toHash = `${now}-${randomPart}`;
|
|
48
|
+
const encoder = new TextEncoder();
|
|
49
|
+
const data = encoder.encode(toHash);
|
|
50
|
+
const hash = await crypto.subtle.digest('SHA-256', data);
|
|
51
|
+
const hashArray = Array.from(new Uint8Array(hash));
|
|
52
|
+
const hashString = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
53
|
+
const shortHash = hashString.substring(0, 12);
|
|
54
|
+
return this.encodeBase62(parseInt(shortHash, 16));
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
encodeBase62 = num => {
|
|
58
|
+
const base = 26;
|
|
59
|
+
const characters = 'abcdefghijklmnopqrstuvwxyz';
|
|
60
|
+
let result = '';
|
|
61
|
+
while (num > 0) {
|
|
62
|
+
result = characters[num % base] + result;
|
|
63
|
+
num = Math.floor(num / base);
|
|
64
|
+
}
|
|
65
|
+
return result || 'a';
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
initializePeer = async () => {
|
|
69
|
+
console.log('Initializing PeerJS connection...');
|
|
70
|
+
const id = await this.generateTimeBasedPeerID();
|
|
71
|
+
console.log('Generated Peer ID:', id);
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
this.peer = new Peer(id, {
|
|
75
|
+
debug: 2,
|
|
76
|
+
host: 'easyeyes-peer-server.herokuapp.com',
|
|
77
|
+
port: 443,
|
|
78
|
+
secure: true,
|
|
79
|
+
config: {
|
|
80
|
+
iceServers: [
|
|
81
|
+
{
|
|
82
|
+
urls: 'stun:stun.relay.metered.ca:80',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
urls: 'turn:global.relay.metered.ca:80',
|
|
86
|
+
username: 'de884cfc34189cdf1a5dd616',
|
|
87
|
+
credential: 'IcOpouU9/TYBmpHU',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
urls: 'turn:global.relay.metered.ca:80?transport=tcp',
|
|
91
|
+
username: 'de884cfc34189cdf1a5dd616',
|
|
92
|
+
credential: 'IcOpouU9/TYBmpHU',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
urls: 'turn:global.relay.metered.ca:443',
|
|
96
|
+
username: 'de884cfc34189cdf1a5dd616',
|
|
97
|
+
credential: 'IcOpouU9/TYBmpHU',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
urls: 'turns:global.relay.metered.ca:443?transport=tcp',
|
|
101
|
+
username: 'de884cfc34189cdf1a5dd616',
|
|
102
|
+
credential: 'IcOpouU9/TYBmpHU',
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
this.peer.on('open', this.onPeerOpen);
|
|
109
|
+
this.peer.on('connection', this.onPeerConnection);
|
|
110
|
+
this.peer.on('disconnected', this.onPeerDisconnected);
|
|
111
|
+
this.peer.on('close', this.onPeerClose);
|
|
112
|
+
this.peer.on('error', this.onPeerError);
|
|
113
|
+
|
|
114
|
+
console.log('Peer object created:', this.peer);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.error('Failed to initialize PeerJS:', error);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
43
119
|
|
|
44
120
|
onPeerOpen = id => {
|
|
45
121
|
this.displayUpdate('Listener - onPeerOpen');
|
|
122
|
+
console.log('onPeerOpen: ', id);
|
|
46
123
|
// Workaround for peer.reconnect deleting previous id
|
|
47
124
|
try {
|
|
48
125
|
if (id === null) {
|
|
@@ -54,12 +131,12 @@ class Listener extends AudioPeer {
|
|
|
54
131
|
} catch (error) {
|
|
55
132
|
console.error('Error in onPeerOpen: ', error);
|
|
56
133
|
}
|
|
57
|
-
|
|
58
134
|
this.join();
|
|
59
135
|
};
|
|
60
136
|
|
|
61
137
|
onPeerConnection = connection => {
|
|
62
138
|
this.displayUpdate('Listener - onPeerConnection');
|
|
139
|
+
console.log('onPeerConnection: ', connection);
|
|
63
140
|
// Disallow incoming connections
|
|
64
141
|
connection.on('open', () => {
|
|
65
142
|
connection.send('Sender does not accept incoming connections');
|
|
@@ -92,6 +169,7 @@ class Listener extends AudioPeer {
|
|
|
92
169
|
|
|
93
170
|
join = async () => {
|
|
94
171
|
this.displayUpdate('Listener - join');
|
|
172
|
+
console.log(' Creating connection to: ', this.speakerPeerId);
|
|
95
173
|
/**
|
|
96
174
|
* Create the connection between the two Peers.
|
|
97
175
|
*
|
|
@@ -114,7 +192,6 @@ class Listener extends AudioPeer {
|
|
|
114
192
|
this.conn.on('open', async () => {
|
|
115
193
|
this.displayUpdate('Listener - conn open');
|
|
116
194
|
this.connOpen = true;
|
|
117
|
-
await this.getDeviceInfo();
|
|
118
195
|
// this.sendSamplingRate();
|
|
119
196
|
});
|
|
120
197
|
|
|
@@ -127,6 +204,7 @@ class Listener extends AudioPeer {
|
|
|
127
204
|
};
|
|
128
205
|
|
|
129
206
|
startCalibration = async () => {
|
|
207
|
+
await this.getDeviceInfo();
|
|
130
208
|
await this.openAudioStream();
|
|
131
209
|
};
|
|
132
210
|
|