aboutsummaryrefslogtreecommitdiff
path: root/source/client/local_user.ts
diff options
context:
space:
mode:
Diffstat (limited to 'source/client/local_user.ts')
-rw-r--r--source/client/local_user.ts168
1 files changed, 50 insertions, 118 deletions
diff --git a/source/client/local_user.ts b/source/client/local_user.ts
index 7cbd93f..2886a76 100644
--- a/source/client/local_user.ts
+++ b/source/client/local_user.ts
@@ -3,114 +3,83 @@ import { log } from "./logger.ts";
import { RemoteUser } from "./remote_user.ts";
import { get_rnnoise_node } from "./rnnoise.ts";
import { Room } from "./room.ts";
+import { TrackHandle } from "./track_handle.ts";
import { User } from "./user.ts";
export class LocalUser extends User {
-
- private audio_track?: MediaStreamTrack
- private video_track?: MediaStreamTrack
- private screen_track?: MediaStreamTrack
- private audio_disable_cleanup?: () => void
-
mic_gain?: GainNode
default_gain: number = parameter_number("mic_gain", 1)
- controls?: { audio: HTMLElement, video: HTMLElement, mute: HTMLElement, screen: HTMLElement }
-
constructor(room: Room, name: string) {
super(room, name)
this.el.classList.add("local")
this.local = true
this.create_controls()
- if (parameter_bool("audio_enabled", false)) this.enable_audio()
- if (parameter_bool("video_enabled", false)) this.enable_video()
+ this.add_initial_tracks()
+ }
+
+ async add_initial_tracks() {
+ if (parameter_bool("mic_enabled", false)) this.publish_track(await this.create_mic_track())
+ if (parameter_bool("camera_enabled", false)) this.publish_track(await this.create_camera_track())
+ if (parameter_bool("screen_enabled", false)) this.publish_track(await this.create_screen_track())
+ }
+
+ publish_track(t: TrackHandle) {
+ this.room.remote_users.forEach(u => u.peer.addTrack(t.track))
+ this.add_track(t)
+ t.addEventListener("ended", () => {
+ this.room.remote_users.forEach(u => {
+ u.peer.getSenders().forEach(s => {
+ if (s.track == t.track) u.peer.removeTrack(s)
+ })
+ })
+ })
+ }
+
+ add_initial_to_remote(u: RemoteUser) {
+ this.tracks.forEach(t => u.peer.addTrack(t.track))
}
create_controls() {
- const audio_toggle = document.createElement("input")
- const video_toggle = document.createElement("input")
- const mute_toggle = document.createElement("input")
+ const mic_toggle = document.createElement("input")
+ const camera_toggle = document.createElement("input")
const screen_toggle = document.createElement("input")
- audio_toggle.type = video_toggle.type = mute_toggle.type = screen_toggle.type = "button"
- audio_toggle.value = "Audio"
- video_toggle.value = "Video"
+ mic_toggle.type = camera_toggle.type = screen_toggle.type = "button"
+ mic_toggle.value = "Microphone"
+ camera_toggle.value = "Camera"
screen_toggle.value = "Screen"
- mute_toggle.value = "Mute"
- let audio = parameter_bool("audio_enabled", false),
- video = parameter_bool("video_enabled", false),
- mute = parameter_bool("video_enabled", false),
- screen = parameter_bool("screen_enabled", false)
+ const create = async (_e: HTMLElement, tp: Promise<TrackHandle>) => {
+ log("media", "awaiting track")
+ const t = await tp
+ log("media", "got track")
+ this.publish_track(t)
+ }
- audio_toggle.addEventListener("click", () => {
- audio = !audio
- if (audio) this.enable_audio()
- else this.disable_audio()
- })
- video_toggle.addEventListener("click", () => {
- video = !video
- if (video) this.enable_video()
- else this.disable_video()
- })
- screen_toggle.addEventListener("click", () => {
- screen = !screen
- if (screen) this.enable_screen()
- else this.disable_screen()
- })
- mute_toggle.addEventListener("click", () => {
- mute = !mute
- this.mic_gain?.gain?.setValueAtTime(mute ? 0 : this.default_gain, 0)
- if (mute) this.controls?.mute.classList.add("enabled")
- else this.controls?.mute.classList.remove("enabled")
- })
+ mic_toggle.addEventListener("click", () => create(mic_toggle, this.create_mic_track()))
+ camera_toggle.addEventListener("click", () => create(camera_toggle, this.create_camera_track()))
+ screen_toggle.addEventListener("click", () => create(screen_toggle, this.create_screen_track()))
const el = document.createElement("div")
el.classList.add("local-controls")
- el.append(audio_toggle, video_toggle, mute_toggle, screen_toggle)
- this.controls = { video: video_toggle, audio: audio_toggle, mute: mute_toggle, screen: screen_toggle }
+ el.append(mic_toggle, camera_toggle, screen_toggle)
document.body.append(el)
}
- update_view_w() {
- this.update_view()
- if (this.stream.getAudioTracks().length > 0)
- this.controls?.audio.classList.add("enabled")
- else this.controls?.audio.classList.remove("enabled")
-
- if (this.stream.getVideoTracks().length > 0)
- this.controls?.video.classList.add("enabled")
- else this.controls?.video.classList.remove("enabled")
- }
-
- add_initial_to_remote(ru: RemoteUser) {
- if (this.audio_track) ru.peer.addTrack(this.audio_track)
- if (this.video_track) ru.peer.addTrack(this.video_track)
- if (this.screen_track) ru.peer.addTrack(this.screen_track)
- }
- async enable_video() {
- if (this.video_track) return
- log("media", "requesting user media (video)")
+ async create_camera_track() {
+ log("media", "requesting user media (camera)")
const user_media = await window.navigator.mediaDevices.getUserMedia({ video: true })
- const t = this.video_track = user_media.getVideoTracks()[0]
- this.room.remote_users.forEach(u => u.peer.addTrack(t))
- this.stream.addTrack(t)
- this.update_view_w()
+ return new TrackHandle(user_media.getVideoTracks()[0])
}
- async enable_screen() {
- if (this.video_track) return
+ async create_screen_track() {
log("media", "requesting user media (screen)")
const user_media = await window.navigator.mediaDevices.getDisplayMedia({ video: true })
- const t = this.video_track = user_media.getVideoTracks()[0]
- this.room.remote_users.forEach(u => u.peer.addTrack(t))
- this.stream.addTrack(t)
- this.update_view_w()
+ return new TrackHandle(user_media.getVideoTracks()[0])
}
- async enable_audio() {
- if (this.audio_track) return
+ async create_mic_track() {
log("media", "requesting user media (audio)")
-
const use_rnnoise = parameter_bool("rnnoise", true)
const audio_contraints = use_rnnoise ? {
channelCount: { ideal: 1 },
@@ -137,53 +106,16 @@ export class LocalUser extends User {
}
gain.connect(destination)
- this.audio_disable_cleanup = () => {
+ const t = new TrackHandle(destination.stream.getAudioTracks()[0])
+
+ t.addEventListener("ended", () => {
source.disconnect()
if (rnnoise) rnnoise.disconnect()
gain.disconnect()
destination.disconnect()
this.mic_gain = undefined
- }
-
- const t = destination.stream.getAudioTracks()[0]
- this.audio_track = t
- this.room.remote_users.forEach(u => u.peer.addTrack(t))
- this.stream.addTrack(t)
- this.update_view_w()
- }
-
- disable_video() {
- if (!this.video_track) return
- this.room.remote_users.forEach(u => {
- u.peer.getSenders().forEach(s => {
- if (s.track == this.video_track) u.peer.removeTrack(s)
- })
- })
- this.stream.removeTrack(this.video_track)
- this.update_view_w()
- this.video_track = undefined
- }
- disable_screen() {
- if (!this.screen_track) return
- this.room.remote_users.forEach(u => {
- u.peer.getSenders().forEach(s => {
- if (s.track == this.screen_track) u.peer.removeTrack(s)
- })
})
- this.stream.removeTrack(this.screen_track)
- this.update_view_w()
- this.screen_track = undefined
- }
- disable_audio() {
- if (!this.audio_track) return
- if (this.audio_disable_cleanup) this.audio_disable_cleanup()
- this.room.remote_users.forEach(u => {
- u.peer.getSenders().forEach(s => {
- if (s.track == this.audio_track) u.peer.removeTrack(s)
- })
- })
- this.stream.removeTrack(this.audio_track)
- this.update_view_w()
- this.audio_track = undefined
+
+ return t
}
}