From a3cc9f8fb1bf45741b08ce6d383c4d7cc8ea8b1f Mon Sep 17 00:00:00 2001 From: metamuffin Date: Fri, 16 Sep 2022 20:46:58 +0200 Subject: optional streams (2, basic functionality) --- client-web/source/resource/mod.ts | 4 ++++ client-web/source/resource/track.ts | 17 ++++++++++++++++- client-web/source/track_handle.ts | 6 +++++- client-web/source/user/local.ts | 4 ++++ client-web/source/user/mod.ts | 2 +- client-web/source/user/remote.ts | 13 +++++++++---- 6 files changed, 39 insertions(+), 7 deletions(-) (limited to 'client-web/source') 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 @@ /// 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 = 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 ?? "") }) } -- cgit v1.2.3-70-g09d2