aboutsummaryrefslogtreecommitdiff
path: root/client-web/source/resource/track.ts
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2022-10-03 11:28:16 +0200
committermetamuffin <metamuffin@disroot.org>2022-10-03 11:28:16 +0200
commit4e99a3325318c902cd78ea9f760f46d79acde5c0 (patch)
treecc2bc54f4a0eb27db2b5d38dfbb785c1e9b84bd6 /client-web/source/resource/track.ts
parentfa44b02da29a0bd1b60026d4f6ffd6c9748a09da (diff)
downloadkeks-meet-4e99a3325318c902cd78ea9f760f46d79acde5c0.tar
keks-meet-4e99a3325318c902cd78ea9f760f46d79acde5c0.tar.bz2
keks-meet-4e99a3325318c902cd78ea9f760f46d79acde5c0.tar.zst
riesencommit (part 1)
Diffstat (limited to 'client-web/source/resource/track.ts')
-rw-r--r--client-web/source/resource/track.ts160
1 files changed, 125 insertions, 35 deletions
diff --git a/client-web/source/resource/track.ts b/client-web/source/resource/track.ts
index 1ae6f94..0e99416 100644
--- a/client-web/source/resource/track.ts
+++ b/client-web/source/resource/track.ts
@@ -4,48 +4,138 @@
Copyright (C) 2022 metamuffin <metamuffin@disroot.org>
*/
/// <reference lib="dom" />
-
import { ProvideInfo } from "../../../common/packets.d.ts";
+import { ebutton, ediv } from "../helper.ts";
+import { log } from "../logger.ts";
+import { on_pref_changed, PREFS } from "../preferences/mod.ts";
+import { get_rnnoise_node } from "../rnnoise.ts";
import { TrackHandle } from "../track_handle.ts";
-import { User } from "../user/mod.ts";
-import { Resource } from "./mod.ts";
+import { LocalResource, ResourceHandlerDecl } from "./mod.ts";
-export class TrackResource extends Resource {
- constructor(user: User, info: ProvideInfo, track?: TrackHandle) {
- super(user, info)
- this.track = track
+export const resource_track: ResourceHandlerDecl = {
+ kind: "track",
+ new_remote: (info, _user, enable) => {
+ const enable_button = ebutton("Enable", {
+ onclick: self => {
+ self.disabled = true;
+ self.textContent = "Awaiting track…";
+ enable()
+ }
+ })
+ return {
+ info,
+ el: ediv({}, enable_button),
+ on_statechange() { },
+ on_enable(track, disable) {
+ this.el.removeChild(enable_button)
+ this.el.append(ebutton("Disable", {
+ onclick: (self) => {
+ disable()
+ this.el.appendChild(enable_button)
+ self.disabled = true
+ enable_button.disabled = false
+ enable_button.textContent = "Enable";
+ self.remove()
+ }
+ }))
+ if (!(track instanceof TrackHandle)) return console.warn("aservuoivasretuoip");
+ this.el.append(create_track_display(track))
+ }
+ }
}
+}
- destroy() {
- this.track?.end()
- super.destroy()
+export function new_local_track(info: ProvideInfo, track: TrackHandle): LocalResource {
+ return {
+ info,
+ el: ediv({},
+ create_track_display(track)
+ ),
+ destroy() { track.end() },
+ on_request(_user, _create_channel) {
+ return track
+ }
}
+}
- on_track(track: TrackHandle): HTMLElement {
- const el = document.createElement("div")
- const is_video = track.kind == "video"
- const media_el = is_video ? document.createElement("video") : document.createElement("audio")
- const stream = new MediaStream([track.track])
- media_el.srcObject = stream
- media_el.classList.add("media")
- media_el.autoplay = true
- media_el.controls = true
- if (track.local) media_el.muted = true
- el.append(media_el)
+function create_track_display(track: TrackHandle): HTMLElement {
+ const el = document.createElement("div")
+ const is_video = track.kind == "video"
+ const media_el = is_video ? document.createElement("video") : document.createElement("audio")
+ const stream = new MediaStream([track.track])
+ media_el.srcObject = stream
+ media_el.classList.add("media")
+ media_el.autoplay = true
+ media_el.controls = true
+ if (track.local) media_el.muted = true
+ el.append(media_el)
+ track.addEventListener("ended", () => {
+ media_el.srcObject = null // TODO // TODO figure out why i wrote todo here
+ el.remove()
+ })
+ return el
+}
- if (track.local) {
- const end_button = document.createElement("button")
- end_button.textContent = "End"
- end_button.addEventListener("click", () => {
- track?.end()
- })
- el.append(end_button)
+export async function create_camera_res() {
+ log("media", "requesting user media (camera)")
+ const user_media = await window.navigator.mediaDevices.getUserMedia({
+ video: {
+ facingMode: { ideal: PREFS.camera_facing_mode },
+ frameRate: { ideal: PREFS.video_fps },
+ width: { ideal: PREFS.video_resolution }
}
- this.el.append(el)
- track.addEventListener("ended", () => {
- media_el.srcObject = null // TODO
- el.remove()
- })
- return el
+ })
+ const t = new TrackHandle(user_media.getVideoTracks()[0], true)
+ return new_local_track({ id: t.id, kind: "track", track_kind: "video", label: "Camera" }, t)
+}
+
+export async function create_screencast_res() {
+ log("media", "requesting user media (screen)")
+ const user_media = await window.navigator.mediaDevices.getDisplayMedia({
+ video: {
+ frameRate: { ideal: PREFS.video_fps },
+ width: { ideal: PREFS.video_resolution }
+ },
+ })
+ const t = new TrackHandle(user_media.getVideoTracks()[0], true)
+ return new_local_track({ id: t.id, kind: "track", track_kind: "video", label: "Screen" }, t)
+}
+
+export async function create_mic_res() {
+ log("media", "requesting user media (audio)")
+ const user_media = await window.navigator.mediaDevices.getUserMedia({
+ audio: {
+ channelCount: { ideal: 1 },
+ noiseSuppression: { ideal: PREFS.rnnoise ? false : PREFS.native_noise_suppression },
+ echoCancellation: { ideal: PREFS.echo_cancellation },
+ autoGainControl: { ideal: PREFS.auto_gain_control },
+ }
+ })
+ const context = new AudioContext()
+ const source = context.createMediaStreamSource(user_media)
+ const destination = context.createMediaStreamDestination()
+ const gain = context.createGain()
+ gain.gain.value = PREFS.microphone_gain
+ const clear_gain_cb = on_pref_changed("microphone_gain", () => gain.gain.value = PREFS.microphone_gain)
+
+ let rnnoise: RNNoiseNode;
+ if (PREFS.rnnoise) {
+ rnnoise = await get_rnnoise_node(context)
+ source.connect(rnnoise)
+ rnnoise.connect(gain)
+ } else {
+ source.connect(gain)
}
-} \ No newline at end of file
+ gain.connect(destination)
+
+ const t = new TrackHandle(destination.stream.getAudioTracks()[0], true)
+ t.addEventListener("ended", () => {
+ user_media.getTracks().forEach(t => t.stop())
+ source.disconnect()
+ if (rnnoise) rnnoise.disconnect()
+ gain.disconnect()
+ clear_gain_cb()
+ destination.disconnect()
+ })
+ return new_local_track({ id: t.id, kind: "track", track_kind: "audio", label: "Microphone" }, t)
+}