diff options
-rw-r--r-- | client-web/source/resource/mod.ts | 4 | ||||
-rw-r--r-- | client-web/source/resource/track.ts | 17 | ||||
-rw-r--r-- | client-web/source/track_handle.ts | 6 | ||||
-rw-r--r-- | client-web/source/user/local.ts | 4 | ||||
-rw-r--r-- | client-web/source/user/mod.ts | 2 | ||||
-rw-r--r-- | client-web/source/user/remote.ts | 13 | ||||
-rw-r--r-- | common/packets.d.ts | 2 | ||||
-rw-r--r-- | readme.md | 1 |
8 files changed, 41 insertions, 8 deletions
diff --git a/client-web/source/resource/mod.ts b/client-web/source/resource/mod.ts index d437260..3091a45 100644 --- a/client-web/source/resource/mod.ts +++ b/client-web/source/resource/mod.ts @@ -9,6 +9,8 @@ export type ChannelState = "running" | "disconnected" export abstract class Resource { el: HTMLElement = ediv({ class: ["channel"] }) + on_destroy = () => { } + constructor( public user: User, public info: ProvideInfo, @@ -23,6 +25,8 @@ export abstract class Resource { this._state = value } + destroy() { this.on_destroy() } + abstract create_element(): HTMLElement abstract create_preview(): HTMLElement diff --git a/client-web/source/resource/track.ts b/client-web/source/resource/track.ts index ee87917..f58e020 100644 --- a/client-web/source/resource/track.ts +++ b/client-web/source/resource/track.ts @@ -1,12 +1,27 @@ import { ProvideInfo } from "../../../common/packets.d.ts"; import { ebutton } from "../helper.ts"; import { TrackHandle } from "../track_handle.ts"; +import { LocalUser } from "../user/local.ts"; import { User } from "../user/mod.ts"; import { Resource } from "./mod.ts"; export class TrackResource extends Resource { - constructor(user: User, info: ProvideInfo, public track?: TrackHandle) { + private _track?: TrackHandle + constructor(user: User, info: ProvideInfo, track?: TrackHandle) { super(user, info) + this.track = track + } + + get track() { return this._track } + set track(value: TrackHandle | undefined) { + const handle_end = () => { + this.track = undefined + if (this.user instanceof LocalUser) this.destroy() + } + this._track?.removeEventListener("ended", handle_end) + this._track = value + this._track?.addEventListener("ended", handle_end) + this.update_el() } create_preview(): HTMLElement { diff --git a/client-web/source/track_handle.ts b/client-web/source/track_handle.ts index 98b2b2f..1bb9265 100644 --- a/client-web/source/track_handle.ts +++ b/client-web/source/track_handle.ts @@ -1,6 +1,8 @@ /// <reference lib="dom" /> export class TrackHandle extends EventTarget { + stream: MediaStream // this is used to create an id that is persistent across clients + constructor( public track: MediaStreamTrack, public local = false @@ -15,12 +17,14 @@ export class TrackHandle extends EventTarget { // drop all references to help gc track.onunmute = track.onmute = track.onended = null }) + + this.stream = new MediaStream([track]) } get kind() { return this.track.kind } get label() { return this.track.label } get muted() { return this.track.muted } - get id() { return this.track.id } + get id() { return this.stream.id } //!! end() { this.track.stop(); this.dispatchEvent(new CustomEvent("ended")) } } diff --git a/client-web/source/user/local.ts b/client-web/source/user/local.ts index 4b057ee..e5d22e5 100644 --- a/client-web/source/user/local.ts +++ b/client-web/source/user/local.ts @@ -72,6 +72,10 @@ export class LocalUser extends User { this.el.append(r.el) const provide: ProvideInfo = r.info this.room.signaling.send_relay({ provide }) + r.on_destroy = () => { + this.el.removeChild(r.el); + this.room.signaling.send_relay({ provide_stop: { id: r.info.id } }) + } } send_track(t: TrackHandle) { diff --git a/client-web/source/user/mod.ts b/client-web/source/user/mod.ts index 59c58b7..85c6960 100644 --- a/client-web/source/user/mod.ts +++ b/client-web/source/user/mod.ts @@ -6,7 +6,7 @@ import { Resource } from "../resource/mod.ts"; import { Room } from "../room.ts" export abstract class User { - protected el: HTMLElement + public el: HTMLElement public local = false public resources: Map<string, Resource> = new Map() diff --git a/client-web/source/user/remote.ts b/client-web/source/user/remote.ts index 110fd40..59d811a 100644 --- a/client-web/source/user/remote.ts +++ b/client-web/source/user/remote.ts @@ -31,11 +31,15 @@ export class RemoteUser extends User { this.update_stats() } this.peer.ontrack = ev => { + console.log(ev) const t = ev.track - log("media", `remote track: ${this.display_name}`, t) - const r = this.resources.get(t.label) - if (r instanceof TrackResource) { r.track = new TrackHandle(t); r.state = "running" } + const id = ev.streams[0].id + if (!id) return log({ scope: "media", warn: true }, "got a track without stream") + const r = this.resources.get(id) + if (!r) return log({ scope: "media", warn: true }, "got an unassociated track") + if (r instanceof TrackResource) r.track = new TrackHandle(t); else log({ scope: "media", warn: true }, "got a track for a resource that should use data channel") + log("media", `remote track: ${this.display_name}`, t) this.update_stats() } this.peer.onnegotiationneeded = () => { @@ -73,6 +77,7 @@ export class RemoteUser extends User { if (PREFS.notify_join) notify(`${this.display_name} joined`) } if (message.provide) { + console.log(message.provide.id); const d = Resource.create(this, message.provide) if (!d) return this.el.append(d.el) @@ -87,7 +92,7 @@ export class RemoteUser extends User { if (!r) return log({ scope: "*", warn: true }, "somebody requested an unknown resource") if (r instanceof TrackResource) { if (!r.track) throw new Error("local resources not avail"); - const sender = this.peer.addTrack(r.track.track) + const sender = this.peer.addTrack(r.track.track, r.track.stream) this.senders.set(r.track.id, sender) r.track.addEventListener("end", () => { this.senders.delete(r.track?.id ?? "") }) } diff --git a/common/packets.d.ts b/common/packets.d.ts index 4ef4ad4..38059a3 100644 --- a/common/packets.d.ts +++ b/common/packets.d.ts @@ -35,7 +35,7 @@ export interface /* enum */ RelayMessage { } export interface ChatMessage { text?: string, image?: string } export interface ProvideInfo { - id: string, + id: string, // for datachannels this is `label`, for tracks this will be the `id` of the only associated stream. kind: "audio" | "video" | "file" label?: string size?: number @@ -115,6 +115,7 @@ keks-meet _tries_ to be secure. However I am not a security expert. The current - How do we implement global hotkeys? - Tray icon for native - Pin js by bookmarking data:text/html loader page +- Maybe group tracks in streams to make sure everything is in sync ## Protocol |