{"code":"(window.webpackJsonpGUI=window.webpackJsonpGUI||[]).push([[42],{1386:function(e,t,n){\"use strict\";t.a=(e,t)=>{const n=document.createElement(\"a\");if(document.body.appendChild(n),navigator.msSaveOrOpenBlob)navigator.msSaveOrOpenBlob(t,e);else if(\"download\"in HTMLAnchorElement.prototype){const o=window.URL.createObjectURL(t);n.href=o,n.download=e,n.type=t.type,n.click(),window.setTimeout((()=>{document.body.removeChild(n),window.URL.revokeObjectURL(o)}),1e3)}else{let e=window.open(\"\",\"_blank\");const n=new FileReader;n.onloadend=function(){e.location.href=n.result,e=null},n.readAsDataURL(t)}}},1450:function(e,t,n){(e.exports=n(9)(!1)).push([e.i,'.mediaRecorderPopup {\\n box-sizing: border-box;\\n width: 700px;\\n max-height: min(800px, 80vh);\\n max-width: 85%;\\n margin-top: 12vh;\\n overflow-y: auto;\\n margin-left: auto;\\n margin-right: auto;\\n}\\n\\n.mediaRecorderPopupContent {\\n padding: 1.5rem 2.25rem;\\n}\\n\\n.mediaRecorderPopup p {\\n font-size: 1rem;\\n margin: 0.5rem auto;\\n}\\n\\n.mediaRecorderPopup p :last-child {\\n margin-left: 1rem;\\n}\\n\\n.mediaRecorderPopup[dir=\"rtl\"] p :last-child {\\n margin-left: 0;\\n margin-right: 1rem;\\n}\\n\\np.mediaRecorderPopupOption {\\n display: flex;\\n align-items: center;\\n}\\n\\n.mediaRecorderPopupOption input[type=\"checkbox\"] {\\n height: 1.5rem;\\n}\\n\\n#recordOptionSecondsInput,\\n#recordOptionDelayInput {\\n width: 6rem;\\n}\\n\\n.mediaRecorderPopupButtons {\\n margin-top: 1.5rem;\\n}\\n\\n.mediaRecorderPopupButtons button {\\n margin-left: 0.5rem;\\n}\\n\\n.mediaRecorderPopupButtons button:nth-of-type(1) {\\n color: black;\\n}\\n',\"\"])},1547:function(e,t,n){\"use strict\";n.r(t),n.d(t,\"resources\",(function(){return r}));var o=n(1386),a=n(1450);const r={\"userscript.js\":async e=>{let t,n,a,{addon:r,console:c,msg:i}=e,d=!1,l=!1,s=null,p=null,m=null,u=[];const b=[\"video/webm; codecs=vp9\",\"video/webm\",\"video/mp4\"].find((e=>MediaRecorder.isTypeSupported(e))),h=b.split(\";\")[0].split(\"/\")[1];for(;;){const e=await r.tab.waitForElement('div[class*=\"menu-bar_file-group\"] > div:last-child:not(.sa-record)',{markAsSeen:!0,reduxEvents:[\"scratch-gui/mode/SET_PLAYER\",\"fontsLoaded/SET_FONTS_LOADED\",\"scratch-gui/locales/SELECT_LOCALE\"]}),g=()=>{const{backdrop:e,container:t,content:n,closeButton:o,remove:a}=r.tab.createModal(i(\"option-title\"),{isOpen:!0,useEditorClasses:!0});t.classList.add(\"mediaRecorderPopup\"),n.classList.add(\"mediaRecorderPopupContent\"),n.appendChild(Object.assign(document.createElement(\"p\"),{textContent:i(\"record-description\",{extension:\".\".concat(h)}),className:\"recordOptionDescription\"}));const c=document.createElement(\"p\"),d=Object.assign(document.createElement(\"input\"),{type:\"number\",min:1,max:600,defaultValue:30,id:\"recordOptionSecondsInput\",className:r.tab.scratchClass(\"prompt_variable-name-text-input\")}),l=Object.assign(document.createElement(\"label\"),{htmlFor:\"recordOptionSecondsInput\",textContent:i(\"record-duration\")});c.appendChild(l),c.appendChild(d),n.appendChild(c);const s=document.createElement(\"p\"),p=Object.assign(document.createElement(\"input\"),{type:\"number\",min:0,max:600,defaultValue:0,id:\"recordOptionDelayInput\",className:r.tab.scratchClass(\"prompt_variable-name-text-input\")}),m=Object.assign(document.createElement(\"label\"),{htmlFor:\"recordOptionDelayInput\",textContent:i(\"start-delay\")});s.appendChild(m),s.appendChild(p),n.appendChild(s);const u=Object.assign(document.createElement(\"p\"),{className:\"mediaRecorderPopupOption\"}),b=Object.assign(document.createElement(\"input\"),{type:\"checkbox\",defaultChecked:!0,id:\"recordOptionAudioInput\"}),g=Object.assign(document.createElement(\"label\"),{htmlFor:\"recordOptionAudioInput\",textContent:i(\"record-audio\"),title:i(\"record-audio-description\")});u.appendChild(b),u.appendChild(g),n.appendChild(u);const O=Object.assign(document.createElement(\"p\"),{className:\"mediaRecorderPopupOption\"}),C=Object.assign(document.createElement(\"input\"),{type:\"checkbox\",defaultChecked:!1,id:\"recordOptionMicInput\"}),E=Object.assign(document.createElement(\"label\"),{htmlFor:\"recordOptionMicInput\",textContent:i(\"record-mic\")});O.appendChild(C),O.appendChild(E),n.appendChild(O);const f=Object.assign(document.createElement(\"p\"),{className:\"mediaRecorderPopupOption\"}),v=Object.assign(document.createElement(\"input\"),{type:\"checkbox\",defaultChecked:!0,id:\"recordOptionFlagInput\"}),w=Object.assign(document.createElement(\"label\"),{htmlFor:\"recordOptionFlagInput\",textContent:i(\"record-after-flag\")});f.appendChild(v),f.appendChild(w),n.appendChild(f);const x=Object.assign(document.createElement(\"p\"),{className:\"mediaRecorderPopupOption\"}),k=Object.assign(document.createElement(\"input\"),{type:\"checkbox\",defaultChecked:!0,id:\"recordOptionStopInput\"}),R=Object.assign(document.createElement(\"label\"),{htmlFor:\"recordOptionStopInput\",textContent:i(\"record-until-stop\")});v.addEventListener(\"change\",(()=>{(k.disabled=!v.checked)&&(R.title=i(\"record-until-stop-disabled\",{afterFlagOption:i(\"record-after-flag\")}))})),x.appendChild(k),x.appendChild(R),n.appendChild(x);let y=null;const P=new Promise((e=>{y=e}));let S=null;e.addEventListener(\"click\",(()=>S(null))),o.addEventListener(\"click\",(()=>S(null))),S=e=>{y(e),a()};const j=Object.assign(document.createElement(\"div\"),{className:r.tab.scratchClass(\"prompt_button-row\",{others:\"mediaRecorderPopupButtons\"})}),T=Object.assign(document.createElement(\"button\"),{textContent:i(\"cancel\")});T.addEventListener(\"click\",(()=>S(null)),{once:!0}),j.appendChild(T);const L=Object.assign(document.createElement(\"button\"),{textContent:i(\"start\"),className:r.tab.scratchClass(\"prompt_ok-button\")});return L.addEventListener(\"click\",(()=>S({secs:Number(d.value),delay:Number(p.value),audioEnabled:b.checked,micEnabled:C.checked,waitUntilFlag:v.checked,useStopSign:!k.disabled&&k.checked})),{once:!0}),j.appendChild(L),n.appendChild(j),P},O=()=>{d=!1,t.textContent=i(\"record\"),t.title=\"\",n=null,u=[],clearTimeout(a),a=0,m&&(r.tab.traps.vm.runtime.off(\"PROJECT_STOP_ALL\",m),m=null)},C=e=>{if(l)return r.tab.traps.vm.runtime.off(\"PROJECT_START\",s),l=!1,s=null,p.abort(),p=null,void O();d&&n&&\"inactive\"!==n.state&&(e?O():(n.onstop=()=>{var e,t,n;const a=new Blob(u,{type:b});Object(o.a)(\"\".concat((null===(e=r.tab.redux.state)||void 0===e||null===(t=e.preview)||void 0===t||null===(n=t.projectInfo)||void 0===n?void 0:n.title)||\"video\",\".\").concat(h),a),O()},n.stop()))},E=async e=>{const o=Math.min(600,Math.max(1,e.secs));u=[],d=!0;const h=r.tab.traps.vm;let g;if(e.micEnabled)try{g=await navigator.mediaDevices.getUserMedia({audio:!0})}catch(t){if(\"NotAllowedError\"!==t.name&&\"NotFoundError\"!==t.name)throw t;e.micEnabled=!1}if(e.waitUntilFlag){l=!0,Object.assign(t,{textContent:i(\"click-flag\"),title:i(\"click-flag-description\")}),p=new AbortController;try{await Promise.race([new Promise((e=>{s=()=>e(),h.runtime.once(\"PROJECT_START\",s)})),new Promise(((e,t)=>{p.signal.addEventListener(\"abort\",(()=>t(\"aborted\")),{once:!0})}))])}catch(e){if(\"aborted\"===e.message)return;throw e}}l=!1,s=p=null;const O=new MediaStream,E=h.runtime.renderer.canvas.captureStream();O.addTrack(E.getVideoTracks()[0]);const f=new AudioContext,v=f.createMediaStreamDestination();if(e.audioEnabled){const e=h.runtime.audioEngine.audioContext.createMediaStreamDestination();h.runtime.audioEngine.inputNode.connect(e);f.createMediaStreamSource(e.stream).connect(v)}if(e.micEnabled){f.createMediaStreamSource(g).connect(v)}(e.audioEnabled||e.micEnabled)&&O.addTrack(v.stream.getAudioTracks()[0]),n=new MediaRecorder(O,{mimeType:b}),n.ondataavailable=e=>{u.push(e.data)},n.onerror=e=>{c.warn(\"Recorder error:\",e.error),C(!0)},a=setTimeout((()=>C(!1)),1e3*o),e.useStopSign&&(m=()=>C(),h.runtime.once(\"PROJECT_STOP_ALL\",m));const w=e.delay||0,x=Math.floor(w);for(let e=0;esetTimeout(e,975)));setTimeout((()=>{t.textContent=i(\"stop\"),n.start(1e3)}),1e3*(w-x))};t||(t=Object.assign(document.createElement(\"div\"),{className:\"sa-record \"+e.className,textContent:i(\"record\")}),t.addEventListener(\"click\",(async()=>{if(d)C();else{const e=await g();if(!e)return void c.log(\"Canceled\");E(e)}}))),e.parentElement.appendChild(t)}},\"style.css\":n.n(a).a}}}]);","name":"js/pentapod/addon-entry-mediarecorder.5186d5b817776b0ba182.js","input":"(window[\"webpackJsonpGUI\"] = window[\"webpackJsonpGUI\"] || []).push([[42],{\n\n/***/ 1386:\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n// From https://github.com/scratchfoundation/scratch-gui/blob/develop/src/lib/download-blob.js\n/* harmony default export */ __webpack_exports__[\"a\"] = ((filename, blob) => {\n const downloadLink = document.createElement(\"a\");\n document.body.appendChild(downloadLink);\n\n // Use special ms version if available to get it working on Edge.\n if (navigator.msSaveOrOpenBlob) {\n navigator.msSaveOrOpenBlob(blob, filename);\n return;\n }\n if (\"download\" in HTMLAnchorElement.prototype) {\n const url = window.URL.createObjectURL(blob);\n downloadLink.href = url;\n downloadLink.download = filename;\n downloadLink.type = blob.type;\n downloadLink.click();\n // remove the link after a timeout to prevent a crash on iOS 13 Safari\n window.setTimeout(() => {\n document.body.removeChild(downloadLink);\n window.URL.revokeObjectURL(url);\n }, 1000);\n } else {\n // iOS 12 Safari, open a new page and set href to data-uri\n let popup = window.open(\"\", \"_blank\");\n const reader = new FileReader();\n reader.onloadend = function () {\n popup.location.href = reader.result;\n popup = null;\n };\n reader.readAsDataURL(blob);\n }\n});\n\n/***/ }),\n\n/***/ 1450:\n/***/ (function(module, exports, __webpack_require__) {\n\nexports = module.exports = __webpack_require__(9)(false);\n// imports\n\n\n// module\nexports.push([module.i, \".mediaRecorderPopup {\\n box-sizing: border-box;\\n width: 700px;\\n max-height: min(800px, 80vh);\\n max-width: 85%;\\n margin-top: 12vh;\\n overflow-y: auto;\\n margin-left: auto;\\n margin-right: auto;\\n}\\n\\n.mediaRecorderPopupContent {\\n padding: 1.5rem 2.25rem;\\n}\\n\\n.mediaRecorderPopup p {\\n font-size: 1rem;\\n margin: 0.5rem auto;\\n}\\n\\n.mediaRecorderPopup p :last-child {\\n margin-left: 1rem;\\n}\\n\\n.mediaRecorderPopup[dir=\\\"rtl\\\"] p :last-child {\\n margin-left: 0;\\n margin-right: 1rem;\\n}\\n\\np.mediaRecorderPopupOption {\\n display: flex;\\n align-items: center;\\n}\\n\\n.mediaRecorderPopupOption input[type=\\\"checkbox\\\"] {\\n height: 1.5rem;\\n}\\n\\n#recordOptionSecondsInput,\\n#recordOptionDelayInput {\\n width: 6rem;\\n}\\n\\n.mediaRecorderPopupButtons {\\n margin-top: 1.5rem;\\n}\\n\\n.mediaRecorderPopupButtons button {\\n margin-left: 0.5rem;\\n}\\n\\n.mediaRecorderPopupButtons button:nth-of-type(1) {\\n color: black;\\n}\\n\", \"\"]);\n\n// exports\n\n\n/***/ }),\n\n/***/ 1547:\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n// ESM COMPAT FLAG\n__webpack_require__.r(__webpack_exports__);\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, \"resources\", function() { return /* binding */ resources; });\n\n// EXTERNAL MODULE: ./src/addons/libraries/common/cs/download-blob.js\nvar download_blob = __webpack_require__(1386);\n\n// CONCATENATED MODULE: ./src/addons/addons/mediarecorder/userscript.js\n\n/* harmony default export */ var userscript = (async _ref => {\n let {\n addon,\n console,\n msg\n } = _ref;\n let recordElem;\n let isRecording = false;\n let isWaitingForFlag = false;\n let waitingForFlagFunc = null;\n let abortController = null;\n let stopSignFunc = null;\n let recordBuffer = [];\n let recorder;\n let timeout;\n const mimeType = [\n // Chrome and Firefox only support encoding as webm\n // VP9 is preferred as its playback is better supported across platforms\n \"video/webm; codecs=vp9\",\n // Firefox only supports encoding VP8\n \"video/webm\",\n // Safari only supports encoding H264 as mp4\n \"video/mp4\"].find(i => MediaRecorder.isTypeSupported(i));\n const fileExtension = mimeType.split(\";\")[0].split(\"/\")[1];\n while (true) {\n const elem = await addon.tab.waitForElement('div[class*=\"menu-bar_file-group\"] > div:last-child:not(.sa-record)', {\n markAsSeen: true,\n reduxEvents: [\"scratch-gui/mode/SET_PLAYER\", \"fontsLoaded/SET_FONTS_LOADED\", \"scratch-gui/locales/SELECT_LOCALE\"]\n });\n const getOptions = () => {\n const {\n backdrop,\n container,\n content,\n closeButton,\n remove\n } = addon.tab.createModal(msg(\"option-title\"), {\n isOpen: true,\n useEditorClasses: true\n });\n container.classList.add(\"mediaRecorderPopup\");\n content.classList.add(\"mediaRecorderPopupContent\");\n content.appendChild(Object.assign(document.createElement(\"p\"), {\n textContent: msg(\"record-description\", {\n extension: \".\".concat(fileExtension)\n }),\n className: \"recordOptionDescription\"\n }));\n\n // Seconds\n const recordOptionSeconds = document.createElement(\"p\");\n const recordOptionSecondsInput = Object.assign(document.createElement(\"input\"), {\n type: \"number\",\n min: 1,\n max: 600,\n defaultValue: 30,\n id: \"recordOptionSecondsInput\",\n className: addon.tab.scratchClass(\"prompt_variable-name-text-input\")\n });\n const recordOptionSecondsLabel = Object.assign(document.createElement(\"label\"), {\n htmlFor: \"recordOptionSecondsInput\",\n textContent: msg(\"record-duration\")\n });\n recordOptionSeconds.appendChild(recordOptionSecondsLabel);\n recordOptionSeconds.appendChild(recordOptionSecondsInput);\n content.appendChild(recordOptionSeconds);\n\n // Delay\n const recordOptionDelay = document.createElement(\"p\");\n const recordOptionDelayInput = Object.assign(document.createElement(\"input\"), {\n type: \"number\",\n min: 0,\n max: 600,\n defaultValue: 0,\n id: \"recordOptionDelayInput\",\n className: addon.tab.scratchClass(\"prompt_variable-name-text-input\")\n });\n const recordOptionDelayLabel = Object.assign(document.createElement(\"label\"), {\n htmlFor: \"recordOptionDelayInput\",\n textContent: msg(\"start-delay\")\n });\n recordOptionDelay.appendChild(recordOptionDelayLabel);\n recordOptionDelay.appendChild(recordOptionDelayInput);\n content.appendChild(recordOptionDelay);\n\n // Audio\n const recordOptionAudio = Object.assign(document.createElement(\"p\"), {\n className: \"mediaRecorderPopupOption\"\n });\n const recordOptionAudioInput = Object.assign(document.createElement(\"input\"), {\n type: \"checkbox\",\n defaultChecked: true,\n id: \"recordOptionAudioInput\"\n });\n const recordOptionAudioLabel = Object.assign(document.createElement(\"label\"), {\n htmlFor: \"recordOptionAudioInput\",\n textContent: msg(\"record-audio\"),\n title: msg(\"record-audio-description\")\n });\n recordOptionAudio.appendChild(recordOptionAudioInput);\n recordOptionAudio.appendChild(recordOptionAudioLabel);\n content.appendChild(recordOptionAudio);\n\n // Mic\n const recordOptionMic = Object.assign(document.createElement(\"p\"), {\n className: \"mediaRecorderPopupOption\"\n });\n const recordOptionMicInput = Object.assign(document.createElement(\"input\"), {\n type: \"checkbox\",\n defaultChecked: false,\n id: \"recordOptionMicInput\"\n });\n const recordOptionMicLabel = Object.assign(document.createElement(\"label\"), {\n htmlFor: \"recordOptionMicInput\",\n textContent: msg(\"record-mic\")\n });\n recordOptionMic.appendChild(recordOptionMicInput);\n recordOptionMic.appendChild(recordOptionMicLabel);\n content.appendChild(recordOptionMic);\n\n // Green flag\n const recordOptionFlag = Object.assign(document.createElement(\"p\"), {\n className: \"mediaRecorderPopupOption\"\n });\n const recordOptionFlagInput = Object.assign(document.createElement(\"input\"), {\n type: \"checkbox\",\n defaultChecked: true,\n id: \"recordOptionFlagInput\"\n });\n const recordOptionFlagLabel = Object.assign(document.createElement(\"label\"), {\n htmlFor: \"recordOptionFlagInput\",\n textContent: msg(\"record-after-flag\")\n });\n recordOptionFlag.appendChild(recordOptionFlagInput);\n recordOptionFlag.appendChild(recordOptionFlagLabel);\n content.appendChild(recordOptionFlag);\n\n // Stop sign\n const recordOptionStop = Object.assign(document.createElement(\"p\"), {\n className: \"mediaRecorderPopupOption\"\n });\n const recordOptionStopInput = Object.assign(document.createElement(\"input\"), {\n type: \"checkbox\",\n defaultChecked: true,\n id: \"recordOptionStopInput\"\n });\n const recordOptionStopLabel = Object.assign(document.createElement(\"label\"), {\n htmlFor: \"recordOptionStopInput\",\n textContent: msg(\"record-until-stop\")\n });\n recordOptionFlagInput.addEventListener(\"change\", () => {\n const disabled = recordOptionStopInput.disabled = !recordOptionFlagInput.checked;\n if (disabled) {\n recordOptionStopLabel.title = msg(\"record-until-stop-disabled\", {\n afterFlagOption: msg(\"record-after-flag\")\n });\n }\n });\n recordOptionStop.appendChild(recordOptionStopInput);\n recordOptionStop.appendChild(recordOptionStopLabel);\n content.appendChild(recordOptionStop);\n let resolvePromise = null;\n const optionPromise = new Promise(resolve => {\n resolvePromise = resolve;\n });\n let handleOptionClose = null;\n backdrop.addEventListener(\"click\", () => handleOptionClose(null));\n closeButton.addEventListener(\"click\", () => handleOptionClose(null));\n handleOptionClose = value => {\n resolvePromise(value);\n remove();\n };\n const buttonRow = Object.assign(document.createElement(\"div\"), {\n className: addon.tab.scratchClass(\"prompt_button-row\", {\n others: \"mediaRecorderPopupButtons\"\n })\n });\n const cancelButton = Object.assign(document.createElement(\"button\"), {\n textContent: msg(\"cancel\")\n });\n cancelButton.addEventListener(\"click\", () => handleOptionClose(null), {\n once: true\n });\n buttonRow.appendChild(cancelButton);\n const startButton = Object.assign(document.createElement(\"button\"), {\n textContent: msg(\"start\"),\n className: addon.tab.scratchClass(\"prompt_ok-button\")\n });\n startButton.addEventListener(\"click\", () => handleOptionClose({\n secs: Number(recordOptionSecondsInput.value),\n delay: Number(recordOptionDelayInput.value),\n audioEnabled: recordOptionAudioInput.checked,\n micEnabled: recordOptionMicInput.checked,\n waitUntilFlag: recordOptionFlagInput.checked,\n useStopSign: !recordOptionStopInput.disabled && recordOptionStopInput.checked\n }), {\n once: true\n });\n buttonRow.appendChild(startButton);\n content.appendChild(buttonRow);\n return optionPromise;\n };\n const disposeRecorder = () => {\n isRecording = false;\n recordElem.textContent = msg(\"record\");\n recordElem.title = \"\";\n recorder = null;\n recordBuffer = [];\n clearTimeout(timeout);\n timeout = 0;\n if (stopSignFunc) {\n addon.tab.traps.vm.runtime.off(\"PROJECT_STOP_ALL\", stopSignFunc);\n stopSignFunc = null;\n }\n };\n const stopRecording = force => {\n if (isWaitingForFlag) {\n addon.tab.traps.vm.runtime.off(\"PROJECT_START\", waitingForFlagFunc);\n isWaitingForFlag = false;\n waitingForFlagFunc = null;\n abortController.abort();\n abortController = null;\n disposeRecorder();\n return;\n }\n if (!isRecording || !recorder || recorder.state === \"inactive\") return;\n if (force) {\n disposeRecorder();\n } else {\n recorder.onstop = () => {\n var _addon$tab$redux$stat, _addon$tab$redux$stat2, _addon$tab$redux$stat3;\n const blob = new Blob(recordBuffer, {\n type: mimeType\n });\n Object(download_blob[\"a\" /* default */])(\"\".concat(((_addon$tab$redux$stat = addon.tab.redux.state) === null || _addon$tab$redux$stat === void 0 ? void 0 : (_addon$tab$redux$stat2 = _addon$tab$redux$stat.preview) === null || _addon$tab$redux$stat2 === void 0 ? void 0 : (_addon$tab$redux$stat3 = _addon$tab$redux$stat2.projectInfo) === null || _addon$tab$redux$stat3 === void 0 ? void 0 : _addon$tab$redux$stat3.title) || \"video\", \".\").concat(fileExtension), blob);\n disposeRecorder();\n };\n recorder.stop();\n }\n };\n const startRecording = async opts => {\n // Timer\n const secs = Math.min(600, Math.max(1, opts.secs));\n\n // Initialize MediaRecorder\n recordBuffer = [];\n isRecording = true;\n const vm = addon.tab.traps.vm;\n let micStream;\n if (opts.micEnabled) {\n // Show permission dialog before green flag is clicked\n try {\n micStream = await navigator.mediaDevices.getUserMedia({\n audio: true\n });\n } catch (e) {\n if (e.name !== \"NotAllowedError\" && e.name !== \"NotFoundError\") throw e;\n opts.micEnabled = false;\n }\n }\n if (opts.waitUntilFlag) {\n isWaitingForFlag = true;\n Object.assign(recordElem, {\n textContent: msg(\"click-flag\"),\n title: msg(\"click-flag-description\")\n });\n abortController = new AbortController();\n try {\n await Promise.race([new Promise(resolve => {\n waitingForFlagFunc = () => resolve();\n vm.runtime.once(\"PROJECT_START\", waitingForFlagFunc);\n }), new Promise((_, reject) => {\n abortController.signal.addEventListener(\"abort\", () => reject(\"aborted\"), {\n once: true\n });\n })]);\n } catch (e) {\n if (e.message === \"aborted\") return;\n throw e;\n }\n }\n isWaitingForFlag = false;\n waitingForFlagFunc = abortController = null;\n const stream = new MediaStream();\n const videoStream = vm.runtime.renderer.canvas.captureStream();\n stream.addTrack(videoStream.getVideoTracks()[0]);\n const ctx = new AudioContext();\n const dest = ctx.createMediaStreamDestination();\n if (opts.audioEnabled) {\n const mediaStreamDestination = vm.runtime.audioEngine.audioContext.createMediaStreamDestination();\n vm.runtime.audioEngine.inputNode.connect(mediaStreamDestination);\n const audioSource = ctx.createMediaStreamSource(mediaStreamDestination.stream);\n audioSource.connect(dest);\n }\n if (opts.micEnabled) {\n const micSource = ctx.createMediaStreamSource(micStream);\n micSource.connect(dest);\n }\n if (opts.audioEnabled || opts.micEnabled) {\n stream.addTrack(dest.stream.getAudioTracks()[0]);\n }\n recorder = new MediaRecorder(stream, {\n mimeType\n });\n recorder.ondataavailable = e => {\n recordBuffer.push(e.data);\n };\n recorder.onerror = e => {\n console.warn(\"Recorder error:\", e.error);\n stopRecording(true);\n };\n timeout = setTimeout(() => stopRecording(false), secs * 1000);\n if (opts.useStopSign) {\n stopSignFunc = () => stopRecording();\n vm.runtime.once(\"PROJECT_STOP_ALL\", stopSignFunc);\n }\n\n // Delay\n const delay = opts.delay || 0;\n const roundedDelay = Math.floor(delay);\n for (let index = 0; index < roundedDelay; index++) {\n recordElem.textContent = msg(\"starting-in\", {\n secs: roundedDelay - index\n });\n await new Promise(resolve => setTimeout(resolve, 975));\n }\n setTimeout(() => {\n recordElem.textContent = msg(\"stop\");\n recorder.start(1000);\n }, (delay - roundedDelay) * 1000);\n };\n if (!recordElem) {\n recordElem = Object.assign(document.createElement(\"div\"), {\n className: \"sa-record \" + elem.className,\n textContent: msg(\"record\")\n });\n recordElem.addEventListener(\"click\", async () => {\n if (isRecording) {\n stopRecording();\n } else {\n const opts = await getOptions();\n if (!opts) {\n console.log(\"Canceled\");\n return;\n }\n startRecording(opts);\n }\n });\n }\n elem.parentElement.appendChild(recordElem);\n }\n});\n// EXTERNAL MODULE: ./node_modules/css-loader!./src/addons/addons/mediarecorder/style.css\nvar style = __webpack_require__(1450);\nvar style_default = /*#__PURE__*/__webpack_require__.n(style);\n\n// CONCATENATED MODULE: ./src/addons/addons/mediarecorder/_runtime_entry.js\n/* generated by pull.js */\n\n\nconst resources = {\n \"userscript.js\": userscript,\n \"style.css\": style_default.a\n};\n\n/***/ })\n\n}]);","inputSourceMap":null}