diff options
Diffstat (limited to 'client-web/public')
-rw-r--r-- | client-web/public/app.html | 20 | ||||
-rw-r--r-- | client-web/public/assets/rnnoise/LICENSE | 21 | ||||
-rw-r--r-- | client-web/public/assets/rnnoise/rnnoise-processor.js | 41 | ||||
-rw-r--r-- | client-web/public/assets/rnnoise/rnnoise-processor.wasm | bin | 0 -> 124830 bytes | |||
-rw-r--r-- | client-web/public/assets/rnnoise/rnnoise-runtime.js | 76 | ||||
-rw-r--r-- | client-web/public/assets/style/logger.css | 42 | ||||
-rw-r--r-- | client-web/public/assets/style/master.css | 115 | ||||
-rw-r--r-- | client-web/public/start.html | 52 |
8 files changed, 367 insertions, 0 deletions
diff --git a/client-web/public/app.html b/client-web/public/app.html new file mode 100644 index 0000000..d88abbd --- /dev/null +++ b/client-web/public/app.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + + <script defer async type="module" src="/bundle.js"></script> + <link rel="stylesheet" href="/style/master.css" /> + + <title>keks-meet</title> + </head> + + <body> + <p> + keks-meet needs evil javascript to be enabled. Don't be afraid though, all + the code is free (AGPL-3.0-only)! Look at it on + <a href="https://codeberg.org/metamuffin/keks-meet">codeberg</a> + </p> + </body> +</html> diff --git a/client-web/public/assets/rnnoise/LICENSE b/client-web/public/assets/rnnoise/LICENSE new file mode 100644 index 0000000..4824556 --- /dev/null +++ b/client-web/public/assets/rnnoise/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 WONG Tin Chi Timothy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/client-web/public/assets/rnnoise/rnnoise-processor.js b/client-web/public/assets/rnnoise/rnnoise-processor.js new file mode 100644 index 0000000..5b594a4 --- /dev/null +++ b/client-web/public/assets/rnnoise/rnnoise-processor.js @@ -0,0 +1,41 @@ +"use strict"; +{ + let b, d; + registerProcessor( + "rnnoise", + class extends AudioWorkletProcessor { + constructor(a) { + super({ + ...a, + numberOfInputs: 1, + numberOfOutputs: 1, + outputChannelCount: [1], + }); + b || + (d = new Float32Array( + (b = new WebAssembly.Instance(a.processorOptions.module) + .exports).memory.buffer + )); + this.state = b.newState(); + this.alive = !0; + this.port.onmessage = ({ data: a }) => { + this.alive && + (a + ? this.port.postMessage({ vadProb: b.getVadProb(this.state) }) + : ((this.alive = !1), b.deleteState(this.state))); + }; + } + process(a, c, e) { + if (!a[0][0]) return 1 + if (this.alive) + return ( + d.set(a[0][0], b.getInput(this.state) / 4), + (a = c[0][0]), + (c = b.pipe(this.state, a.length) / 4) && + a.set(d.subarray(c, c + a.length)), + !0 + ); + } + } + ); +} diff --git a/client-web/public/assets/rnnoise/rnnoise-processor.wasm b/client-web/public/assets/rnnoise/rnnoise-processor.wasm Binary files differnew file mode 100644 index 0000000..86fea35 --- /dev/null +++ b/client-web/public/assets/rnnoise/rnnoise-processor.wasm diff --git a/client-web/public/assets/rnnoise/rnnoise-runtime.js b/client-web/public/assets/rnnoise/rnnoise-runtime.js new file mode 100644 index 0000000..f69c568 --- /dev/null +++ b/client-web/public/assets/rnnoise/rnnoise-runtime.js @@ -0,0 +1,76 @@ +"use strict"; +{ + const g = document.currentScript.src.match(/(.*\/)?/)[0], + h = ( + WebAssembly.compileStreaming || + (async (a) => await WebAssembly.compile(await (await a).arrayBuffer())) + )(fetch(g + "rnnoise-processor.wasm")); + let k, c, e; + window.RNNoiseNode = + ((window.AudioWorkletNode || + (window.AudioWorkletNode = window.webkitAudioWorkletNode)) && + class extends AudioWorkletNode { + static async register(a) { + k = await h; + await a.audioWorklet.addModule(g + "rnnoise-processor.js"); + } + constructor(a) { + super(a, "rnnoise", { + channelCountMode: "explicit", + channelCount: 1, + channelInterpretation: "speakers", + numberOfInputs: 1, + numberOfOutputs: 1, + outputChannelCount: [1], + processorOptions: { module: k }, + }); + this.port.onmessage = ({ data: b }) => { + b = Object.assign(new Event("status"), b); + this.dispatchEvent(b); + if (this.onstatus) this.onstatus(b); + }; + } + update(a) { + this.port.postMessage(a); + } + }) || + ((window.ScriptProcessorNode || + (window.ScriptProcessorNode = window.webkitScriptProcessorNode)) && + Object.assign( + function (a) { + const b = a.createScriptProcessor(512, 1, 1), + d = c.newState(); + let f = !0; + b.onaudioprocess = ({ inputBuffer: b, outputBuffer: a }) => { + f && + (e.set(b.getChannelData(0), c.getInput(d) / 4), + (b = a.getChannelData(0)), + (a = c.pipe(d, b.length) / 4) && + b.set(e.subarray(a, a + b.length))); + }; + b.update = (a) => { + if (f) + if (a) { + if ( + ((a = Object.assign(new Event("status"), { + vadProb: c.getVadProb(d), + })), + b.dispatchEvent(a), + b.onstatus) + ) + b.onstatus(a); + } else (f = !1), c.deleteState(d); + }; + return b; + }, + { + register: async () => { + c || + (e = new Float32Array( + (c = (await WebAssembly.instantiate(await h)) + .exports).memory.buffer + )); + }, + } + )); +} diff --git a/client-web/public/assets/style/logger.css b/client-web/public/assets/style/logger.css new file mode 100644 index 0000000..cb76586 --- /dev/null +++ b/client-web/public/assets/style/logger.css @@ -0,0 +1,42 @@ +.logger-container { + position: absolute; + top: 0px; + right: 0px; + transition: width 1s; + + background-color: rgba(0, 0, 0, 0.376); + border-radius: 0.2em; + border: 0px solid transparent; + padding: 0.2em; +} + +.logger-line { + font-size: 1em; + height: 1.2em; + + animation-name: appear, disappear; + animation-timing-function: linear, linear; + animation-delay: 0s, 3s; + animation-duration: 0.3s, 1s; + animation-fill-mode: forwards, forwards; +} + +@keyframes appear { + from { + margin-top: -1.2em; + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes disappear { + from { + opacity: 1; + } + to { + margin-top: -1.2em; + opacity: 0; + } +} diff --git a/client-web/public/assets/style/master.css b/client-web/public/assets/style/master.css new file mode 100644 index 0000000..0b9e205 --- /dev/null +++ b/client-web/public/assets/style/master.css @@ -0,0 +1,115 @@ +@import url("https://s.metamuffin.org/static/font-ubuntu/include.css"); +@import url("./logger.css"); + +* { + font-family: "Ubuntu", sans-serif; + font-weight: 300; + color: white; + margin: 0px; + padding: 0px; +} + +:root { + --bg: #263238; + --bg-dark: #000a12; + --bg-light: #354b58; + --bg-lighter: #4f5b62; + --bg-disabled: #720000; + --bg-enabled: #097200; + --ac: #4a148c; + --ac-light: #7c43bd; + --ac-dark: #12005e; +} + +body { + background-color: var(--bg-dark); +} + +h2 { + font-weight: 700; + margin: 1em; +} + +input[type="button"], +button { + padding: 0.5em; + margin: 0.25em; + background-color: var(--bg-light); + border: 0px solid transparent; + border-radius: 3px; +} +input[type="button"]:hover, +button:hover { + background-color: var(--bg-lighter); +} +input[type="button"].enabled, +button.enabled { + background-color: var(--bg-enabled); +} +input[type="text"] { + background-color: var(--bg-dark); + border: 1px solid var(--ac-light); +} + +.local-controls { + background-color: var(--bg); + padding: 0.5em; + position: absolute; + bottom: 0.5em; + border: 0px solid transparent; + border-radius: 5px; + left: 50%; + transform: translateX(-50%); + z-index: 100; +} + +.room { + width: 100%; + height: 100%; +} + +.user { + background-color: var(--bg); + border: 0px soly transparent; + border-radius: 5px; + padding: 1em; + vertical-align: baseline; + min-width: 10em; + margin: 0.5em; +} + +.user .info .name { + font-weight: 400; +} +.user.local .info .name { + text-decoration: underline; +} + +.media { + max-height: 30vh; + border: 0px solid transparent; + border-radius: 5px; +} + +.start-box { + position: absolute; + top: 50vh; + left: 50vw; + transform: translate(-50%, -50%); +} +.start-box p { + margin-bottom: 0.5em; +} +.start-box input[type="text"] { + margin: 0.5em; + font-size: 32px; +} + +.menu-overlay { + position: absolute; + bottom: 0px; + right: 0px; + display: block; + text-align: right; +} + diff --git a/client-web/public/start.html b/client-web/public/start.html new file mode 100644 index 0000000..0852f8b --- /dev/null +++ b/client-web/public/start.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + + <script defer async type="module" src="/bundle.js"></script> + <link rel="stylesheet" href="/style/master.css" /> + + <title>keks-meet</title> + </head> + + <body> + <h2>keks-meet</h2> + <p>A web conferencing application using webrtc</p> + <p> + keks-meet is free software! It is licenced under the terms of the + third version of the GNU Affero General Public Licence only. + </p> + <p> + To get started, just enter a unique idenfier, click 'Join', then + share the URL with your partner. + </p> + <noscript> + keks-meet needs evil javascript to be enabled. Don't be afraid + though, all the code is free (AGPL-3.0-only)! Look at it on + <a href="https://codeberg.org/metamuffin/keks-meet">codeberg</a> + </noscript> + <script> + const room_input = document.createElement("input"); + room_input.type = "text"; + room_input.id = "room-id-input"; + room_input.placeholder = "Room ID (leave blank for random id)"; + + const submit = document.createElement("input"); + submit.type = "button"; + submit.addEventListener("click", () => { + if (room_input.value.length == 0) + room_input.value = Math.floor(Math.random() * 10000) + .toString(16) + .padStart(5, "0"); + window.location.pathname = `/${encodeURIComponent( + room_input.value + )}`; + }); + submit.value = "Join room!"; + + el.classList.add("start-box"); + el.append(room_input, document.createElement("br"), submit); + </script> + </body> +</html> |