@moq/publish 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/broadcast.d.ts +2 -2
- package/element.d.ts +17 -7
- package/element.d.ts.map +1 -1
- package/element.js +117 -88
- package/element.js.map +1 -1
- package/index.js +2 -2
- package/package.json +3 -3
- package/{screen-Dz_GBTAe.js → screen-BORpmf_D.js} +23 -31
- package/{screen-Dz_GBTAe.js.map → screen-BORpmf_D.js.map} +1 -1
- package/ui/index.js +197 -197
- package/ui/index.js.map +1 -1
package/broadcast.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import * as Video from "./video";
|
|
|
9
9
|
export type BroadcastProps = {
|
|
10
10
|
connection?: Moq.Connection.Established | Signal<Moq.Connection.Established | undefined>;
|
|
11
11
|
enabled?: boolean | Signal<boolean>;
|
|
12
|
-
|
|
12
|
+
name?: Moq.Path.Valid | Signal<Moq.Path.Valid | undefined>;
|
|
13
13
|
audio?: Audio.EncoderProps;
|
|
14
14
|
video?: Video.Props;
|
|
15
15
|
location?: Location.Props;
|
|
@@ -22,7 +22,7 @@ export declare class Broadcast {
|
|
|
22
22
|
static readonly CATALOG_TRACK = "catalog.json";
|
|
23
23
|
connection: Signal<Moq.Connection.Established | undefined>;
|
|
24
24
|
enabled: Signal<boolean>;
|
|
25
|
-
|
|
25
|
+
name: Signal<Moq.Path.Valid | undefined>;
|
|
26
26
|
audio: Audio.Encoder;
|
|
27
27
|
video: Video.Root;
|
|
28
28
|
location: Location.Root;
|
package/element.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import * as Moq from "@moq/lite";
|
|
2
2
|
import { Broadcast } from "./broadcast";
|
|
3
3
|
import * as Source from "./source";
|
|
4
|
-
declare const OBSERVED: readonly ["url", "name", "
|
|
4
|
+
declare const OBSERVED: readonly ["url", "name", "muted", "invisible", "source"];
|
|
5
5
|
type Observed = (typeof OBSERVED)[number];
|
|
6
6
|
type SourceType = "camera" | "screen" | "file";
|
|
7
7
|
export default class MoqPublish extends HTMLElement {
|
|
8
8
|
#private;
|
|
9
|
-
static observedAttributes: readonly ["url", "name", "
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
static observedAttributes: readonly ["url", "name", "muted", "invisible", "source"];
|
|
10
|
+
state: {
|
|
11
|
+
source: Moq.Signals.Signal<File | SourceType | undefined>;
|
|
12
|
+
muted: Moq.Signals.Signal<boolean>;
|
|
13
|
+
invisible: Moq.Signals.Signal<boolean>;
|
|
14
|
+
};
|
|
15
15
|
connection: Moq.Connection.Reload;
|
|
16
16
|
broadcast: Broadcast;
|
|
17
17
|
video: Moq.Signals.Signal<Source.Camera | Source.Screen | undefined>;
|
|
@@ -22,6 +22,16 @@ export default class MoqPublish extends HTMLElement {
|
|
|
22
22
|
connectedCallback(): void;
|
|
23
23
|
disconnectedCallback(): void;
|
|
24
24
|
attributeChangedCallback(name: Observed, oldValue: string | null, newValue: string | null): void;
|
|
25
|
+
get url(): URL | undefined;
|
|
26
|
+
set url(value: string | URL | undefined);
|
|
27
|
+
get name(): Moq.Path.Valid | undefined;
|
|
28
|
+
set name(value: string | Moq.Path.Valid | undefined);
|
|
29
|
+
get source(): SourceType | File | undefined;
|
|
30
|
+
set source(value: SourceType | File | undefined);
|
|
31
|
+
get muted(): boolean;
|
|
32
|
+
set muted(value: boolean);
|
|
33
|
+
get invisible(): boolean;
|
|
34
|
+
set invisible(value: boolean);
|
|
25
35
|
}
|
|
26
36
|
declare global {
|
|
27
37
|
interface HTMLElementTagNameMap {
|
package/element.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC,QAAA,MAAM,QAAQ,0DAA2D,CAAC;AAC1E,KAAK,QAAQ,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1C,KAAK,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAO/C,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;;IAClD,MAAM,CAAC,kBAAkB,2DAAY;IAIrC,KAAK;;;;MAIH;IAEF,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;IAClC,SAAS,EAAE,SAAS,CAAC;IAIrB,KAAK,gEAAoE;IACzE,KAAK,oEAAwE;IAC7E,IAAI,8CAAkD;IAUtD,OAAO,qBAAgB;;IAuEvB,iBAAiB;IAIjB,oBAAoB;IAIpB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAmGzF,IAAI,GAAG,IAAI,GAAG,GAAG,SAAS,CAEzB;IAED,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,EAEtC;IAED,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAErC;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,SAAS,EAElD;IAED,IAAI,MAAM,IAAI,UAAU,GAAG,IAAI,GAAG,SAAS,CAE1C;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EAE9C;IAED,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,EAEvB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,SAAS,CAAC,KAAK,EAAE,OAAO,EAE3B;CACD;AAID,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,aAAa,EAAE,UAAU,CAAC;KAC1B;CACD"}
|
package/element.js
CHANGED
|
@@ -1,141 +1,170 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { Signal as
|
|
3
|
-
import { B as
|
|
4
|
-
const
|
|
5
|
-
class
|
|
6
|
-
static observedAttributes =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import * as c from "@moq/lite";
|
|
2
|
+
import { Signal as o, Effect as u } from "@moq/signals";
|
|
3
|
+
import { B as d, C as h, M as b, S as v, F as g } from "./screen-BORpmf_D.js";
|
|
4
|
+
const m = ["url", "name", "muted", "invisible", "source"], p = new FinalizationRegistry((l) => l.close());
|
|
5
|
+
class w extends HTMLElement {
|
|
6
|
+
static observedAttributes = m;
|
|
7
|
+
// Reactive state for element properties that are also HTML attributes.
|
|
8
|
+
// Access these Signals directly for reactive subscriptions (e.g. effect.get(el.state.source)).
|
|
9
|
+
state = {
|
|
10
|
+
source: new o(void 0),
|
|
11
|
+
muted: new o(!1),
|
|
12
|
+
invisible: new o(!1)
|
|
13
|
+
};
|
|
13
14
|
connection;
|
|
14
15
|
broadcast;
|
|
15
|
-
#
|
|
16
|
-
video = new
|
|
17
|
-
audio = new
|
|
18
|
-
file = new
|
|
16
|
+
#n = new o(void 0);
|
|
17
|
+
video = new o(void 0);
|
|
18
|
+
audio = new o(void 0);
|
|
19
|
+
file = new o(void 0);
|
|
19
20
|
// The inverse of the `muted` and `invisible` signals.
|
|
20
|
-
#s;
|
|
21
21
|
#e;
|
|
22
|
-
#
|
|
22
|
+
#s;
|
|
23
|
+
#t;
|
|
23
24
|
// Set when the element is connected to the DOM.
|
|
24
|
-
#
|
|
25
|
-
signals = new
|
|
25
|
+
#i = new o(!1);
|
|
26
|
+
signals = new u();
|
|
26
27
|
constructor() {
|
|
27
|
-
super(),
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}), this.broadcast = new u({
|
|
28
|
+
super(), p.register(this, this.signals), this.connection = new c.Connection.Reload({
|
|
29
|
+
enabled: this.#i
|
|
30
|
+
}), this.signals.cleanup(() => this.connection.close()), this.#e = new o(!1), this.#s = new o(!1), this.#t = new o(!1), this.signals.run((s) => {
|
|
31
|
+
const t = s.get(this.state.muted), i = s.get(this.state.invisible);
|
|
32
|
+
this.#e.set(!i), this.#s.set(!t), this.#t.set(!t || !i);
|
|
33
|
+
}), this.broadcast = new d({
|
|
34
34
|
connection: this.connection.established,
|
|
35
|
-
enabled: this.#
|
|
36
|
-
path: this.path,
|
|
35
|
+
enabled: this.#i,
|
|
37
36
|
audio: {
|
|
38
|
-
enabled: this.#
|
|
37
|
+
enabled: this.#s
|
|
39
38
|
},
|
|
40
39
|
video: {
|
|
41
40
|
hd: {
|
|
42
|
-
enabled: this.#
|
|
41
|
+
enabled: this.#e
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
44
|
}), this.signals.cleanup(() => this.broadcast.close());
|
|
46
|
-
const
|
|
47
|
-
this.#
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
if (!
|
|
52
|
-
const
|
|
53
|
-
if (!
|
|
54
|
-
|
|
45
|
+
const e = () => {
|
|
46
|
+
this.#n.set(this.querySelector("video"));
|
|
47
|
+
}, n = new MutationObserver(e);
|
|
48
|
+
n.observe(this, { childList: !0, subtree: !0 }), this.signals.cleanup(() => n.disconnect()), e(), this.signals.run((s) => {
|
|
49
|
+
const t = s.get(this.#n);
|
|
50
|
+
if (!t) return;
|
|
51
|
+
const i = s.get(this.broadcast.video.source);
|
|
52
|
+
if (!i) {
|
|
53
|
+
t.style.display = "none";
|
|
55
54
|
return;
|
|
56
55
|
}
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
t.srcObject = new MediaStream([i]), t.style.display = "block", s.cleanup(() => {
|
|
57
|
+
t.srcObject = null;
|
|
59
58
|
});
|
|
60
|
-
}), this.signals.run(this.#
|
|
59
|
+
}), this.signals.run(this.#o.bind(this));
|
|
61
60
|
}
|
|
62
61
|
connectedCallback() {
|
|
63
|
-
this.#
|
|
62
|
+
this.#i.set(!0);
|
|
64
63
|
}
|
|
65
64
|
disconnectedCallback() {
|
|
66
|
-
this.#
|
|
65
|
+
this.#i.set(!1);
|
|
67
66
|
}
|
|
68
|
-
attributeChangedCallback(
|
|
69
|
-
if (
|
|
70
|
-
if (
|
|
71
|
-
this.url.set(s ? new URL(s) : void 0);
|
|
72
|
-
else if (
|
|
73
|
-
this.
|
|
74
|
-
else if (
|
|
67
|
+
attributeChangedCallback(e, n, s) {
|
|
68
|
+
if (n !== s)
|
|
69
|
+
if (e === "url")
|
|
70
|
+
this.connection.url.set(s ? new URL(s) : void 0);
|
|
71
|
+
else if (e === "name")
|
|
72
|
+
this.broadcast.name.set(s ? c.Path.from(s) : void 0);
|
|
73
|
+
else if (e === "source")
|
|
75
74
|
if (s === "camera" || s === "screen" || s === "file" || s === null)
|
|
76
|
-
this.source.set(s);
|
|
75
|
+
this.state.source.set(s);
|
|
77
76
|
else
|
|
78
77
|
throw new Error(`Invalid source: ${s}`);
|
|
79
|
-
else if (
|
|
80
|
-
this.muted.set(s !== null);
|
|
81
|
-
else if (
|
|
82
|
-
this.invisible.set(s !== null);
|
|
78
|
+
else if (e === "muted")
|
|
79
|
+
this.state.muted.set(s !== null);
|
|
80
|
+
else if (e === "invisible")
|
|
81
|
+
this.state.invisible.set(s !== null);
|
|
83
82
|
else {
|
|
84
|
-
const
|
|
85
|
-
throw new Error(`Invalid attribute: ${
|
|
83
|
+
const t = e;
|
|
84
|
+
throw new Error(`Invalid attribute: ${t}`);
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
|
-
#
|
|
89
|
-
const
|
|
90
|
-
if (!
|
|
91
|
-
if (
|
|
92
|
-
const
|
|
87
|
+
#o(e) {
|
|
88
|
+
const n = e.get(this.state.source);
|
|
89
|
+
if (!n) return;
|
|
90
|
+
if (n === "camera") {
|
|
91
|
+
const t = new h({ enabled: this.#e });
|
|
93
92
|
this.signals.run((r) => {
|
|
94
|
-
const a = r.get(
|
|
93
|
+
const a = r.get(t.source);
|
|
95
94
|
this.broadcast.video.source.set(a);
|
|
96
95
|
});
|
|
97
|
-
const
|
|
96
|
+
const i = new b({ enabled: this.#s });
|
|
98
97
|
this.signals.run((r) => {
|
|
99
|
-
const a = r.get(
|
|
98
|
+
const a = r.get(i.source);
|
|
100
99
|
this.broadcast.audio.source.set(a);
|
|
101
|
-
}),
|
|
102
|
-
|
|
100
|
+
}), e.set(this.video, t), e.set(this.audio, i), e.cleanup(() => {
|
|
101
|
+
t.close(), i.close();
|
|
103
102
|
});
|
|
104
103
|
return;
|
|
105
104
|
}
|
|
106
|
-
if (
|
|
107
|
-
const
|
|
108
|
-
enabled: this.#
|
|
105
|
+
if (n === "screen") {
|
|
106
|
+
const t = new v({
|
|
107
|
+
enabled: this.#t
|
|
109
108
|
});
|
|
110
|
-
this.signals.run((
|
|
111
|
-
const r =
|
|
112
|
-
r && (
|
|
113
|
-
}),
|
|
114
|
-
|
|
109
|
+
this.signals.run((i) => {
|
|
110
|
+
const r = i.get(t.source);
|
|
111
|
+
r && (i.set(this.broadcast.video.source, r.video), i.set(this.broadcast.audio.source, r.audio));
|
|
112
|
+
}), e.set(this.video, t), e.set(this.audio, t), e.cleanup(() => {
|
|
113
|
+
t.close();
|
|
115
114
|
});
|
|
116
115
|
return;
|
|
117
116
|
}
|
|
118
|
-
if (
|
|
119
|
-
const
|
|
117
|
+
if (n === "file" || n instanceof File) {
|
|
118
|
+
const t = new g({
|
|
120
119
|
// If a File is provided, use it directly.
|
|
121
120
|
// TODO: Show a file picker otherwise.
|
|
122
|
-
file:
|
|
123
|
-
enabled: this.#
|
|
121
|
+
file: n instanceof File ? n : void 0,
|
|
122
|
+
enabled: this.#t
|
|
124
123
|
});
|
|
125
|
-
this.signals.run((
|
|
126
|
-
const r =
|
|
124
|
+
this.signals.run((i) => {
|
|
125
|
+
const r = i.get(t.source);
|
|
127
126
|
this.broadcast.video.source.set(r.video), this.broadcast.audio.source.set(r.audio);
|
|
128
|
-
}),
|
|
129
|
-
|
|
127
|
+
}), e.cleanup(() => {
|
|
128
|
+
t.close();
|
|
130
129
|
});
|
|
131
130
|
return;
|
|
132
131
|
}
|
|
133
|
-
const s =
|
|
132
|
+
const s = n;
|
|
134
133
|
throw new Error(`Invalid source: ${s}`);
|
|
135
134
|
}
|
|
135
|
+
get url() {
|
|
136
|
+
return this.connection.url.peek();
|
|
137
|
+
}
|
|
138
|
+
set url(e) {
|
|
139
|
+
this.connection.url.set(e ? new URL(e) : void 0);
|
|
140
|
+
}
|
|
141
|
+
get name() {
|
|
142
|
+
return this.broadcast.name.peek();
|
|
143
|
+
}
|
|
144
|
+
set name(e) {
|
|
145
|
+
this.broadcast.name.set(e ? c.Path.from(e) : void 0);
|
|
146
|
+
}
|
|
147
|
+
get source() {
|
|
148
|
+
return this.state.source.peek();
|
|
149
|
+
}
|
|
150
|
+
set source(e) {
|
|
151
|
+
this.state.source.set(e);
|
|
152
|
+
}
|
|
153
|
+
get muted() {
|
|
154
|
+
return this.state.muted.peek();
|
|
155
|
+
}
|
|
156
|
+
set muted(e) {
|
|
157
|
+
this.state.muted.set(e);
|
|
158
|
+
}
|
|
159
|
+
get invisible() {
|
|
160
|
+
return this.state.invisible.peek();
|
|
161
|
+
}
|
|
162
|
+
set invisible(e) {
|
|
163
|
+
this.state.invisible.set(e);
|
|
164
|
+
}
|
|
136
165
|
}
|
|
137
|
-
customElements.define("moq-publish",
|
|
166
|
+
customElements.define("moq-publish", w);
|
|
138
167
|
export {
|
|
139
|
-
|
|
168
|
+
w as default
|
|
140
169
|
};
|
|
141
170
|
//# sourceMappingURL=element.js.map
|
package/element.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element.js","sources":["../src/element.ts"],"sourcesContent":["import * as Moq from \"@moq/lite\";\nimport { Effect, Signal } from \"@moq/signals\";\nimport { Broadcast } from \"./broadcast\";\nimport * as Source from \"./source\";\n\n// TODO remove name; replaced with path\nconst OBSERVED = [\"url\", \"name\", \"path\", \"muted\", \"invisible\", \"source\"] as const;\ntype Observed = (typeof OBSERVED)[number];\n\ntype SourceType = \"camera\" | \"screen\" | \"file\";\n\n// Close everything when this element is garbage collected.\n// This is primarily to avoid a console.warn that we didn't close() before GC.\n// There's no destructor for web components so this is the best we can do.\nconst cleanup = new FinalizationRegistry<Effect>((signals) => signals.close());\n\nexport default class MoqPublish extends HTMLElement {\n\tstatic observedAttributes = OBSERVED;\n\n\turl = new Signal<URL | undefined>(undefined);\n\tpath = new Signal<Moq.Path.Valid | undefined>(undefined);\n\tsource = new Signal<SourceType | File | undefined>(undefined);\n\n\t// Controls whether audio/video is enabled.\n\tmuted = new Signal(false);\n\tinvisible = new Signal(false);\n\n\tconnection: Moq.Connection.Reload;\n\tbroadcast: Broadcast;\n\n\t#preview = new Signal<HTMLVideoElement | undefined>(undefined);\n\n\tvideo = new Signal<Source.Camera | Source.Screen | undefined>(undefined);\n\taudio = new Signal<Source.Microphone | Source.Screen | undefined>(undefined);\n\tfile = new Signal<Source.File | undefined>(undefined);\n\n\t// The inverse of the `muted` and `invisible` signals.\n\t#videoEnabled: Signal<boolean>;\n\t#audioEnabled: Signal<boolean>;\n\t#eitherEnabled: Signal<boolean>;\n\n\t// Set when the element is connected to the DOM.\n\t#enabled = new Signal(false);\n\n\tsignals = new Effect();\n\n\tconstructor() {\n\t\tsuper();\n\n\t\tcleanup.register(this, this.signals);\n\n\t\tthis.connection = new Moq.Connection.Reload({\n\t\t\turl: this.url,\n\t\t\tenabled: this.#enabled,\n\t\t});\n\t\tthis.signals.cleanup(() => this.connection.close());\n\n\t\t// The inverse of the `muted` and `invisible` signals.\n\t\t// TODO make this.signals.computed to simplify the code.\n\t\tthis.#videoEnabled = new Signal(false);\n\t\tthis.#audioEnabled = new Signal(false);\n\t\tthis.#eitherEnabled = new Signal(false);\n\n\t\tthis.signals.run((effect) => {\n\t\t\tconst muted = effect.get(this.muted);\n\t\t\tconst invisible = effect.get(this.invisible);\n\t\t\tthis.#videoEnabled.set(!invisible);\n\t\t\tthis.#audioEnabled.set(!muted);\n\t\t\tthis.#eitherEnabled.set(!muted || !invisible);\n\t\t});\n\n\t\tthis.broadcast = new Broadcast({\n\t\t\tconnection: this.connection.established,\n\t\t\tenabled: this.#enabled,\n\t\t\tpath: this.path,\n\n\t\t\taudio: {\n\t\t\t\tenabled: this.#audioEnabled,\n\t\t\t},\n\t\t\tvideo: {\n\t\t\t\thd: {\n\t\t\t\t\tenabled: this.#videoEnabled,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\t\tthis.signals.cleanup(() => this.broadcast.close());\n\n\t\t// Watch to see if the preview element is added or removed.\n\t\tconst setPreview = () => {\n\t\t\tthis.#preview.set(this.querySelector(\"video\") as HTMLVideoElement | undefined);\n\t\t};\n\t\tconst observer = new MutationObserver(setPreview);\n\t\tobserver.observe(this, { childList: true, subtree: true });\n\t\tthis.signals.cleanup(() => observer.disconnect());\n\t\tsetPreview();\n\n\t\tthis.signals.run((effect) => {\n\t\t\tconst preview = effect.get(this.#preview);\n\t\t\tif (!preview) return;\n\n\t\t\tconst source = effect.get(this.broadcast.video.source);\n\t\t\tif (!source) {\n\t\t\t\tpreview.style.display = \"none\";\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tpreview.srcObject = new MediaStream([source]);\n\t\t\tpreview.style.display = \"block\";\n\n\t\t\teffect.cleanup(() => {\n\t\t\t\tpreview.srcObject = null;\n\t\t\t});\n\t\t});\n\n\t\tthis.signals.run(this.#runSource.bind(this));\n\t}\n\n\tconnectedCallback() {\n\t\tthis.#enabled.set(true);\n\t}\n\n\tdisconnectedCallback() {\n\t\tthis.#enabled.set(false);\n\t}\n\n\tattributeChangedCallback(name: Observed, oldValue: string | null, newValue: string | null) {\n\t\tif (oldValue === newValue) return;\n\n\t\tif (name === \"url\") {\n\t\t\tthis.url.set(newValue ? new URL(newValue) : undefined);\n\t\t} else if (name === \"name\" || name === \"path\") {\n\t\t\tthis.path.set(newValue ? Moq.Path.from(newValue) : undefined);\n\t\t} else if (name === \"source\") {\n\t\t\tif (newValue === \"camera\" || newValue === \"screen\" || newValue === \"file\" || newValue === null) {\n\t\t\t\tthis.source.set(newValue as SourceType | undefined);\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Invalid source: ${newValue}`);\n\t\t\t}\n\t\t} else if (name === \"muted\") {\n\t\t\tthis.muted.set(newValue !== null);\n\t\t} else if (name === \"invisible\") {\n\t\t\tthis.invisible.set(newValue !== null);\n\t\t} else {\n\t\t\tconst exhaustive: never = name;\n\t\t\tthrow new Error(`Invalid attribute: ${exhaustive}`);\n\t\t}\n\t}\n\n\t#runSource(effect: Effect) {\n\t\tconst source = effect.get(this.source);\n\t\tif (!source) return;\n\n\t\tif (source === \"camera\") {\n\t\t\tconst video = new Source.Camera({ enabled: this.#videoEnabled });\n\t\t\tthis.signals.run((effect) => {\n\t\t\t\tconst source = effect.get(video.source);\n\t\t\t\tthis.broadcast.video.source.set(source);\n\t\t\t});\n\n\t\t\tconst audio = new Source.Microphone({ enabled: this.#audioEnabled });\n\t\t\tthis.signals.run((effect) => {\n\t\t\t\tconst source = effect.get(audio.source);\n\t\t\t\tthis.broadcast.audio.source.set(source);\n\t\t\t});\n\n\t\t\teffect.set(this.video, video);\n\t\t\teffect.set(this.audio, audio);\n\n\t\t\teffect.cleanup(() => {\n\t\t\t\tvideo.close();\n\t\t\t\taudio.close();\n\t\t\t});\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (source === \"screen\") {\n\t\t\tconst screen = new Source.Screen({\n\t\t\t\tenabled: this.#eitherEnabled,\n\t\t\t});\n\n\t\t\tthis.signals.run((effect) => {\n\t\t\t\tconst source = effect.get(screen.source);\n\t\t\t\tif (!source) return;\n\n\t\t\t\teffect.set(this.broadcast.video.source, source.video);\n\t\t\t\teffect.set(this.broadcast.audio.source, source.audio);\n\t\t\t});\n\n\t\t\teffect.set(this.video, screen);\n\t\t\teffect.set(this.audio, screen);\n\n\t\t\teffect.cleanup(() => {\n\t\t\t\tscreen.close();\n\t\t\t});\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (source === \"file\" || source instanceof File) {\n\t\t\tconst fileSource = new Source.File({\n\t\t\t\t// If a File is provided, use it directly.\n\t\t\t\t// TODO: Show a file picker otherwise.\n\t\t\t\tfile: source instanceof File ? source : undefined,\n\t\t\t\tenabled: this.#eitherEnabled,\n\t\t\t});\n\n\t\t\tthis.signals.run((effect) => {\n\t\t\t\tconst source = effect.get(fileSource.source);\n\t\t\t\tthis.broadcast.video.source.set(source.video);\n\t\t\t\tthis.broadcast.audio.source.set(source.audio);\n\t\t\t});\n\n\t\t\teffect.cleanup(() => {\n\t\t\t\tfileSource.close();\n\t\t\t});\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst exhaustive: never = source;\n\t\tthrow new Error(`Invalid source: ${exhaustive}`);\n\t}\n}\n\ncustomElements.define(\"moq-publish\", MoqPublish);\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t\"moq-publish\": MoqPublish;\n\t}\n}\n"],"names":["OBSERVED","cleanup","signals","MoqPublish","Signal","#preview","#videoEnabled","#audioEnabled","#eitherEnabled","#enabled","Effect","Moq","effect","muted","invisible","Broadcast","setPreview","observer","preview","source","#runSource","name","oldValue","newValue","exhaustive","video","Source.Camera","audio","Source.Microphone","screen","Source.Screen","fileSource","Source.File"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"element.js","sources":["../src/element.ts"],"sourcesContent":["import * as Moq from \"@moq/lite\";\nimport { Effect, Signal } from \"@moq/signals\";\nimport { Broadcast } from \"./broadcast\";\nimport * as Source from \"./source\";\n\nconst OBSERVED = [\"url\", \"name\", \"muted\", \"invisible\", \"source\"] as const;\ntype Observed = (typeof OBSERVED)[number];\n\ntype SourceType = \"camera\" | \"screen\" | \"file\";\n\n// Close everything when this element is garbage collected.\n// This is primarily to avoid a console.warn that we didn't close() before GC.\n// There's no destructor for web components so this is the best we can do.\nconst cleanup = new FinalizationRegistry<Effect>((signals) => signals.close());\n\nexport default class MoqPublish extends HTMLElement {\n\tstatic observedAttributes = OBSERVED;\n\n\t// Reactive state for element properties that are also HTML attributes.\n\t// Access these Signals directly for reactive subscriptions (e.g. effect.get(el.state.source)).\n\tstate = {\n\t\tsource: new Signal<SourceType | File | undefined>(undefined),\n\t\tmuted: new Signal(false),\n\t\tinvisible: new Signal(false),\n\t};\n\n\tconnection: Moq.Connection.Reload;\n\tbroadcast: Broadcast;\n\n\t#preview = new Signal<HTMLVideoElement | undefined>(undefined);\n\n\tvideo = new Signal<Source.Camera | Source.Screen | undefined>(undefined);\n\taudio = new Signal<Source.Microphone | Source.Screen | undefined>(undefined);\n\tfile = new Signal<Source.File | undefined>(undefined);\n\n\t// The inverse of the `muted` and `invisible` signals.\n\t#videoEnabled: Signal<boolean>;\n\t#audioEnabled: Signal<boolean>;\n\t#eitherEnabled: Signal<boolean>;\n\n\t// Set when the element is connected to the DOM.\n\t#enabled = new Signal(false);\n\n\tsignals = new Effect();\n\n\tconstructor() {\n\t\tsuper();\n\n\t\tcleanup.register(this, this.signals);\n\n\t\tthis.connection = new Moq.Connection.Reload({\n\t\t\tenabled: this.#enabled,\n\t\t});\n\t\tthis.signals.cleanup(() => this.connection.close());\n\n\t\t// The inverse of the `muted` and `invisible` signals.\n\t\t// TODO make this.signals.computed to simplify the code.\n\t\tthis.#videoEnabled = new Signal(false);\n\t\tthis.#audioEnabled = new Signal(false);\n\t\tthis.#eitherEnabled = new Signal(false);\n\n\t\tthis.signals.run((effect) => {\n\t\t\tconst muted = effect.get(this.state.muted);\n\t\t\tconst invisible = effect.get(this.state.invisible);\n\t\t\tthis.#videoEnabled.set(!invisible);\n\t\t\tthis.#audioEnabled.set(!muted);\n\t\t\tthis.#eitherEnabled.set(!muted || !invisible);\n\t\t});\n\n\t\tthis.broadcast = new Broadcast({\n\t\t\tconnection: this.connection.established,\n\t\t\tenabled: this.#enabled,\n\n\t\t\taudio: {\n\t\t\t\tenabled: this.#audioEnabled,\n\t\t\t},\n\t\t\tvideo: {\n\t\t\t\thd: {\n\t\t\t\t\tenabled: this.#videoEnabled,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\t\tthis.signals.cleanup(() => this.broadcast.close());\n\n\t\t// Watch to see if the preview element is added or removed.\n\t\tconst setPreview = () => {\n\t\t\tthis.#preview.set(this.querySelector(\"video\") as HTMLVideoElement | undefined);\n\t\t};\n\t\tconst observer = new MutationObserver(setPreview);\n\t\tobserver.observe(this, { childList: true, subtree: true });\n\t\tthis.signals.cleanup(() => observer.disconnect());\n\t\tsetPreview();\n\n\t\tthis.signals.run((effect) => {\n\t\t\tconst preview = effect.get(this.#preview);\n\t\t\tif (!preview) return;\n\n\t\t\tconst source = effect.get(this.broadcast.video.source);\n\t\t\tif (!source) {\n\t\t\t\tpreview.style.display = \"none\";\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tpreview.srcObject = new MediaStream([source]);\n\t\t\tpreview.style.display = \"block\";\n\n\t\t\teffect.cleanup(() => {\n\t\t\t\tpreview.srcObject = null;\n\t\t\t});\n\t\t});\n\n\t\tthis.signals.run(this.#runSource.bind(this));\n\t}\n\n\tconnectedCallback() {\n\t\tthis.#enabled.set(true);\n\t}\n\n\tdisconnectedCallback() {\n\t\tthis.#enabled.set(false);\n\t}\n\n\tattributeChangedCallback(name: Observed, oldValue: string | null, newValue: string | null) {\n\t\tif (oldValue === newValue) return;\n\n\t\tif (name === \"url\") {\n\t\t\tthis.connection.url.set(newValue ? new URL(newValue) : undefined);\n\t\t} else if (name === \"name\") {\n\t\t\tthis.broadcast.name.set(newValue ? Moq.Path.from(newValue) : undefined);\n\t\t} else if (name === \"source\") {\n\t\t\tif (newValue === \"camera\" || newValue === \"screen\" || newValue === \"file\" || newValue === null) {\n\t\t\t\tthis.state.source.set(newValue as SourceType | undefined);\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Invalid source: ${newValue}`);\n\t\t\t}\n\t\t} else if (name === \"muted\") {\n\t\t\tthis.state.muted.set(newValue !== null);\n\t\t} else if (name === \"invisible\") {\n\t\t\tthis.state.invisible.set(newValue !== null);\n\t\t} else {\n\t\t\tconst exhaustive: never = name;\n\t\t\tthrow new Error(`Invalid attribute: ${exhaustive}`);\n\t\t}\n\t}\n\n\t#runSource(effect: Effect) {\n\t\tconst source = effect.get(this.state.source);\n\t\tif (!source) return;\n\n\t\tif (source === \"camera\") {\n\t\t\tconst video = new Source.Camera({ enabled: this.#videoEnabled });\n\t\t\tthis.signals.run((effect) => {\n\t\t\t\tconst source = effect.get(video.source);\n\t\t\t\tthis.broadcast.video.source.set(source);\n\t\t\t});\n\n\t\t\tconst audio = new Source.Microphone({ enabled: this.#audioEnabled });\n\t\t\tthis.signals.run((effect) => {\n\t\t\t\tconst source = effect.get(audio.source);\n\t\t\t\tthis.broadcast.audio.source.set(source);\n\t\t\t});\n\n\t\t\teffect.set(this.video, video);\n\t\t\teffect.set(this.audio, audio);\n\n\t\t\teffect.cleanup(() => {\n\t\t\t\tvideo.close();\n\t\t\t\taudio.close();\n\t\t\t});\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (source === \"screen\") {\n\t\t\tconst screen = new Source.Screen({\n\t\t\t\tenabled: this.#eitherEnabled,\n\t\t\t});\n\n\t\t\tthis.signals.run((effect) => {\n\t\t\t\tconst source = effect.get(screen.source);\n\t\t\t\tif (!source) return;\n\n\t\t\t\teffect.set(this.broadcast.video.source, source.video);\n\t\t\t\teffect.set(this.broadcast.audio.source, source.audio);\n\t\t\t});\n\n\t\t\teffect.set(this.video, screen);\n\t\t\teffect.set(this.audio, screen);\n\n\t\t\teffect.cleanup(() => {\n\t\t\t\tscreen.close();\n\t\t\t});\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (source === \"file\" || source instanceof File) {\n\t\t\tconst fileSource = new Source.File({\n\t\t\t\t// If a File is provided, use it directly.\n\t\t\t\t// TODO: Show a file picker otherwise.\n\t\t\t\tfile: source instanceof File ? source : undefined,\n\t\t\t\tenabled: this.#eitherEnabled,\n\t\t\t});\n\n\t\t\tthis.signals.run((effect) => {\n\t\t\t\tconst source = effect.get(fileSource.source);\n\t\t\t\tthis.broadcast.video.source.set(source.video);\n\t\t\t\tthis.broadcast.audio.source.set(source.audio);\n\t\t\t});\n\n\t\t\teffect.cleanup(() => {\n\t\t\t\tfileSource.close();\n\t\t\t});\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst exhaustive: never = source;\n\t\tthrow new Error(`Invalid source: ${exhaustive}`);\n\t}\n\n\tget url(): URL | undefined {\n\t\treturn this.connection.url.peek();\n\t}\n\n\tset url(value: string | URL | undefined) {\n\t\tthis.connection.url.set(value ? new URL(value) : undefined);\n\t}\n\n\tget name(): Moq.Path.Valid | undefined {\n\t\treturn this.broadcast.name.peek();\n\t}\n\n\tset name(value: string | Moq.Path.Valid | undefined) {\n\t\tthis.broadcast.name.set(value ? Moq.Path.from(value) : undefined);\n\t}\n\n\tget source(): SourceType | File | undefined {\n\t\treturn this.state.source.peek();\n\t}\n\n\tset source(value: SourceType | File | undefined) {\n\t\tthis.state.source.set(value);\n\t}\n\n\tget muted(): boolean {\n\t\treturn this.state.muted.peek();\n\t}\n\n\tset muted(value: boolean) {\n\t\tthis.state.muted.set(value);\n\t}\n\n\tget invisible(): boolean {\n\t\treturn this.state.invisible.peek();\n\t}\n\n\tset invisible(value: boolean) {\n\t\tthis.state.invisible.set(value);\n\t}\n}\n\ncustomElements.define(\"moq-publish\", MoqPublish);\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t\"moq-publish\": MoqPublish;\n\t}\n}\n"],"names":["OBSERVED","cleanup","signals","MoqPublish","Signal","#preview","#videoEnabled","#audioEnabled","#eitherEnabled","#enabled","Effect","Moq","effect","muted","invisible","Broadcast","setPreview","observer","preview","source","#runSource","name","oldValue","newValue","exhaustive","video","Source.Camera","audio","Source.Microphone","screen","Source.Screen","fileSource","Source.File","value"],"mappings":"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"}
|
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as e, C as o, D as a, F as r, M as t, S as s } from "./screen-
|
|
2
|
-
import { B as u, i as p, a as _, P as b, u as S, b as f } from "./screen-
|
|
1
|
+
import { E as e, C as o, D as a, F as r, M as t, S as s } from "./screen-BORpmf_D.js";
|
|
2
|
+
import { B as u, i as p, a as _, P as b, u as S, b as f } from "./screen-BORpmf_D.js";
|
|
3
3
|
const n = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
4
4
|
__proto__: null,
|
|
5
5
|
Encoder: e
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moq/publish",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"description": "Publish
|
|
4
|
+
"version": "0.2.1",
|
|
5
|
+
"description": "Publish Media over QUIC broadcasts",
|
|
6
6
|
"license": "(MIT OR Apache-2.0)",
|
|
7
7
|
"repository": "github:moq-dev/moq",
|
|
8
8
|
"exports": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@moq/hang": "^0.2.0",
|
|
37
|
-
"@moq/lite": "^0.1.
|
|
37
|
+
"@moq/lite": "^0.1.4",
|
|
38
38
|
"@moq/signals": "^0.1.3",
|
|
39
39
|
"@moq/ui-core": "^0.1.0"
|
|
40
40
|
}
|
|
@@ -3469,7 +3469,7 @@ var Effect = class _Effect {
|
|
|
3469
3469
|
this.#scheduled = false;
|
|
3470
3470
|
if (this.#fn) {
|
|
3471
3471
|
this.#fn(this);
|
|
3472
|
-
if (DEV && this.#unwatch.length === 0) {
|
|
3472
|
+
if (DEV && this.#dispose !== void 0 && this.#unwatch.length === 0 && this.#dispose.length === 0 && this.#async.length === 0) {
|
|
3473
3473
|
console.warn("Effect did not subscribe to any signals; it will never rerun.", this.#stack);
|
|
3474
3474
|
}
|
|
3475
3475
|
}
|
|
@@ -3629,10 +3629,6 @@ var Effect = class _Effect {
|
|
|
3629
3629
|
target.addEventListener(type, listener, options);
|
|
3630
3630
|
this.cleanup(() => target.removeEventListener(type, listener, options));
|
|
3631
3631
|
}
|
|
3632
|
-
// Reschedule the effect to run again.
|
|
3633
|
-
reload() {
|
|
3634
|
-
this.#schedule();
|
|
3635
|
-
}
|
|
3636
3632
|
// Register a cleanup function.
|
|
3637
3633
|
cleanup(fn) {
|
|
3638
3634
|
if (this.#dispose === void 0) {
|
|
@@ -4047,6 +4043,11 @@ function setInt32(dst, v) {
|
|
|
4047
4043
|
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
4048
4044
|
}
|
|
4049
4045
|
|
|
4046
|
+
// ../lite/src/util/error.ts
|
|
4047
|
+
function unreachable(value) {
|
|
4048
|
+
throw new Error(\`unreachable: \${value}\`);
|
|
4049
|
+
}
|
|
4050
|
+
|
|
4050
4051
|
// ../../node_modules/.bun/async-mutex@0.5.0/node_modules/async-mutex/index.mjs
|
|
4051
4052
|
var E_TIMEOUT = new Error("timeout while waiting for mutex to become available");
|
|
4052
4053
|
var E_ALREADY_LOCKED = new Error("mutex already locked");
|
|
@@ -4590,8 +4591,7 @@ var Publish = class _Publish {
|
|
|
4590
4591
|
await w.bool(this.forward);
|
|
4591
4592
|
await w.u53(0);
|
|
4592
4593
|
} else {
|
|
4593
|
-
|
|
4594
|
-
throw new Error(\`unsupported version: \${_}\`);
|
|
4594
|
+
unreachable(version);
|
|
4595
4595
|
}
|
|
4596
4596
|
}
|
|
4597
4597
|
async encode(w, version) {
|
|
@@ -4637,8 +4637,7 @@ var Publish = class _Publish {
|
|
|
4637
4637
|
forward
|
|
4638
4638
|
});
|
|
4639
4639
|
} else {
|
|
4640
|
-
|
|
4641
|
-
throw new Error(\`unsupported version: \${_}\`);
|
|
4640
|
+
unreachable(version);
|
|
4642
4641
|
}
|
|
4643
4642
|
}
|
|
4644
4643
|
};
|
|
@@ -5010,8 +5009,7 @@ var ClientSetup = class _ClientSetup {
|
|
|
5010
5009
|
}
|
|
5011
5010
|
await this.parameters.encode(w, version);
|
|
5012
5011
|
} else {
|
|
5013
|
-
|
|
5014
|
-
throw new Error(\`unsupported version: \${_}\`);
|
|
5012
|
+
unreachable(version);
|
|
5015
5013
|
}
|
|
5016
5014
|
}
|
|
5017
5015
|
async encode(w, version) {
|
|
@@ -5034,8 +5032,7 @@ var ClientSetup = class _ClientSetup {
|
|
|
5034
5032
|
const parameters = await Parameters.decode(r, version);
|
|
5035
5033
|
return new _ClientSetup({ versions: supportedVersions, parameters });
|
|
5036
5034
|
} else {
|
|
5037
|
-
|
|
5038
|
-
throw new Error(\`unsupported version: \${_}\`);
|
|
5035
|
+
unreachable(version);
|
|
5039
5036
|
}
|
|
5040
5037
|
}
|
|
5041
5038
|
static async decode(r, version) {
|
|
@@ -5057,8 +5054,7 @@ var ServerSetup = class _ServerSetup {
|
|
|
5057
5054
|
await w.u53(this.version);
|
|
5058
5055
|
await this.parameters.encode(w, version);
|
|
5059
5056
|
} else {
|
|
5060
|
-
|
|
5061
|
-
throw new Error(\`unsupported version: \${_}\`);
|
|
5057
|
+
unreachable(version);
|
|
5062
5058
|
}
|
|
5063
5059
|
}
|
|
5064
5060
|
async encode(w, version) {
|
|
@@ -5073,8 +5069,7 @@ var ServerSetup = class _ServerSetup {
|
|
|
5073
5069
|
const parameters = await Parameters.decode(r, version);
|
|
5074
5070
|
return new _ServerSetup({ version: selectedVersion, parameters });
|
|
5075
5071
|
} else {
|
|
5076
|
-
|
|
5077
|
-
throw new Error(\`unsupported version: \${_}\`);
|
|
5072
|
+
unreachable(version);
|
|
5078
5073
|
}
|
|
5079
5074
|
}
|
|
5080
5075
|
static async decode(r, version) {
|
|
@@ -5119,8 +5114,7 @@ var Subscribe = class _Subscribe {
|
|
|
5119
5114
|
await w.u53(2);
|
|
5120
5115
|
await w.u53(0);
|
|
5121
5116
|
} else {
|
|
5122
|
-
|
|
5123
|
-
throw new Error(\`unsupported version: \${_}\`);
|
|
5117
|
+
unreachable(version);
|
|
5124
5118
|
}
|
|
5125
5119
|
}
|
|
5126
5120
|
async encode(w, version) {
|
|
@@ -5172,8 +5166,7 @@ var Subscribe = class _Subscribe {
|
|
|
5172
5166
|
await Parameters.decode(r, version);
|
|
5173
5167
|
return new _Subscribe({ requestId, trackNamespace, trackName, subscriberPriority });
|
|
5174
5168
|
} else {
|
|
5175
|
-
|
|
5176
|
-
throw new Error(\`unsupported version: \${_}\`);
|
|
5169
|
+
unreachable(version);
|
|
5177
5170
|
}
|
|
5178
5171
|
}
|
|
5179
5172
|
};
|
|
@@ -5198,8 +5191,7 @@ var SubscribeOk = class _SubscribeOk {
|
|
|
5198
5191
|
await w.bool(false);
|
|
5199
5192
|
await w.u53(0);
|
|
5200
5193
|
} else {
|
|
5201
|
-
|
|
5202
|
-
throw new Error(\`unsupported version: \${_}\`);
|
|
5194
|
+
unreachable(version);
|
|
5203
5195
|
}
|
|
5204
5196
|
}
|
|
5205
5197
|
async encode(w, version) {
|
|
@@ -5226,8 +5218,7 @@ var SubscribeOk = class _SubscribeOk {
|
|
|
5226
5218
|
}
|
|
5227
5219
|
await Parameters.decode(r, version);
|
|
5228
5220
|
} else {
|
|
5229
|
-
|
|
5230
|
-
throw new Error(\`unsupported version: \${_}\`);
|
|
5221
|
+
unreachable(version);
|
|
5231
5222
|
}
|
|
5232
5223
|
return new _SubscribeOk({ requestId, trackAlias });
|
|
5233
5224
|
}
|
|
@@ -6035,7 +6026,7 @@ class Pe {
|
|
|
6035
6026
|
m *= 1.1;
|
|
6036
6027
|
else
|
|
6037
6028
|
throw new Error(`unknown codec: ${h}`);
|
|
6038
|
-
m = Math.min(m, c.maxBitrate || m);
|
|
6029
|
+
m = Math.round(Math.min(m, c.maxBitrate || m));
|
|
6039
6030
|
const E = {
|
|
6040
6031
|
codec: h,
|
|
6041
6032
|
width: i.width,
|
|
@@ -6246,7 +6237,7 @@ class Xn {
|
|
|
6246
6237
|
static CATALOG_TRACK = "catalog.json";
|
|
6247
6238
|
connection;
|
|
6248
6239
|
enabled;
|
|
6249
|
-
|
|
6240
|
+
name;
|
|
6250
6241
|
audio;
|
|
6251
6242
|
video;
|
|
6252
6243
|
location;
|
|
@@ -6255,12 +6246,12 @@ class Xn {
|
|
|
6255
6246
|
user;
|
|
6256
6247
|
signals = new P();
|
|
6257
6248
|
constructor(n) {
|
|
6258
|
-
this.connection = f.from(n?.connection), this.enabled = f.from(n?.enabled ?? !1), this.
|
|
6249
|
+
this.connection = f.from(n?.connection), this.enabled = f.from(n?.enabled ?? !1), this.name = f.from(n?.name), this.audio = new dn(n?.audio), this.video = new B(n?.video), this.location = new Wn(n?.location), this.chat = new Gn(n?.chat), this.preview = new pe(n?.preview), this.user = new Kn(n?.user), this.signals.run(this.#e.bind(this));
|
|
6259
6250
|
}
|
|
6260
6251
|
#e(n) {
|
|
6261
6252
|
const t = n.getAll([this.enabled, this.connection]);
|
|
6262
6253
|
if (!t) return;
|
|
6263
|
-
const [r, s] = t, i = n.get(this.
|
|
6254
|
+
const [r, s] = t, i = n.get(this.name);
|
|
6264
6255
|
if (i === void 0) return;
|
|
6265
6256
|
const o = new ln.Broadcast();
|
|
6266
6257
|
n.cleanup(() => o.close()), s.publish(i, o), n.spawn(this.#n.bind(this, o, n));
|
|
@@ -6345,7 +6336,8 @@ class Hn {
|
|
|
6345
6336
|
signals = new P();
|
|
6346
6337
|
constructor(n, t) {
|
|
6347
6338
|
this.kind = n, this.preferred = f.from(t?.preferred), this.signals.run((r) => {
|
|
6348
|
-
r.spawn(this.#r.bind(this, r)), r.event(navigator.mediaDevices, "devicechange", () =>
|
|
6339
|
+
r.spawn(this.#r.bind(this, r)), r.event(navigator.mediaDevices, "devicechange", () => this.permission.mutate(() => {
|
|
6340
|
+
}));
|
|
6349
6341
|
}), this.signals.run(this.#s.bind(this));
|
|
6350
6342
|
}
|
|
6351
6343
|
async #r(n) {
|
|
@@ -6583,4 +6575,4 @@ export {
|
|
|
6583
6575
|
aa as i,
|
|
6584
6576
|
da as u
|
|
6585
6577
|
};
|
|
6586
|
-
//# sourceMappingURL=screen-
|
|
6578
|
+
//# sourceMappingURL=screen-BORpmf_D.js.map
|