Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ python:

sphinx:
configuration: py/moq-rs/docs/conf.py
fail_on_warning: true

formats:
- htmlzip
8 changes: 4 additions & 4 deletions cpp/obs/src/moq-source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ static AVCodecID codec_string_to_id(const char *codec, size_t len)
return AV_CODEC_ID_NONE;
}

struct moq_source;

namespace {

struct moq_source;

enum class Decoded { Pending, Ready, Failed };

// A track owns its codec and converted output, including while it is only a candidate.
Expand Down Expand Up @@ -158,8 +158,6 @@ struct Connection {
std::shared_ptr<Track> pending_audio;
};

} // namespace

struct moq_source {
obs_source_t *source = nullptr;

Expand All @@ -184,6 +182,8 @@ struct moq_source {
MoQWorker worker;
};

} // namespace

// Forward declarations
static void moq_source_update(void *data, obs_data_t *settings);
static void moq_source_destroy(void *data);
Expand Down
8 changes: 4 additions & 4 deletions demo/boy/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { resolve } from "path";
import { defineConfig } from "vite";
import solidPlugin from "vite-plugin-solid";
import { crossOriginIsolation } from "../../js/common/vite-plugin-isolate";
import { worklet } from "../../js/common/vite-plugin-worklet";
import { crossOriginIsolation } from "../../js/common/vite-plugin-isolate.ts";
import { worklet } from "../../js/common/vite-plugin-worklet.ts";

export default defineConfig({
root: "src",
envDir: resolve(__dirname),
envDir: resolve(import.meta.dirname),
plugins: [solidPlugin(), worklet(), crossOriginIsolation()],
build: {
target: "esnext",
rollupOptions: {
input: {
main: resolve(__dirname, "src/index.html"),
main: resolve(import.meta.dirname, "src/index.html"),
},
},
},
Expand Down
18 changes: 9 additions & 9 deletions demo/web/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import tailwindcss from "@tailwindcss/vite";
import { resolve } from "path";
import { defineConfig } from "vite";
import solidPlugin from "vite-plugin-solid";
import { crossOriginIsolation } from "../../js/common/vite-plugin-isolate";
import { worklet } from "../../js/common/vite-plugin-worklet";
import { consoleOverlay } from "./console-overlay";
import { openTabs } from "./open-tabs";
import { crossOriginIsolation } from "../../js/common/vite-plugin-isolate.ts";
import { worklet } from "../../js/common/vite-plugin-worklet.ts";
import { consoleOverlay } from "./console-overlay.ts";
import { openTabs } from "./open-tabs.ts";

export default defineConfig({
root: "src",
envDir: resolve(__dirname),
envDir: resolve(import.meta.dirname),
plugins: [
tailwindcss(),
solidPlugin(),
Expand All @@ -25,10 +25,10 @@ export default defineConfig({
sourcemap: process.env.NODE_ENV === "production" ? false : "inline",
rollupOptions: {
input: {
watch: resolve(__dirname, "src/watch.html"),
publish: resolve(__dirname, "src/publish.html"),
stats: resolve(__dirname, "src/stats.html"),
meet: resolve(__dirname, "src/meet.html"),
watch: resolve(import.meta.dirname, "src/watch.html"),
publish: resolve(import.meta.dirname, "src/publish.html"),
stats: resolve(import.meta.dirname, "src/stats.html"),
meet: resolve(import.meta.dirname, "src/meet.html"),
},
},
},
Expand Down
4 changes: 2 additions & 2 deletions js/moq-boy/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ export default defineConfig({
build: {
lib: {
entry: {
index: resolve(__dirname, "src/index.ts"),
element: resolve(__dirname, "src/element.tsx"),
index: resolve(import.meta.dirname, "src/index.ts"),
element: resolve(import.meta.dirname, "src/element.tsx"),
},
formats: ["es"],
},
Expand Down
9 changes: 6 additions & 3 deletions js/net/bench/refresh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ for (const retained of [1, 64, 1024])
while ((await announcements.next())?.kind !== "start") {}
const request = destination.request(Path.from("room"));
while (!request.active.peek()) await request.active.changed();
const remote = request.active.peek()!;
const remote = request.active.peek();
if (!remote) throw new Error("broadcast missing");
const consumers = producers.map((_, i) => remote.track(`data${i}`));
const baseline = consumers.map((track) => track.subscribe());
for (let i = 0; i < tracks; i++) {
const group = producers[i].appendGroup();
group.writeFrame({ payload: new Uint8Array(3) });
group.close();
const received = (await baseline[i].recvGroup())!;
const received = await baseline[i].recvGroup();
if (!received) throw new Error("baseline group missing");
await received.readFrame();
received.close();
}
Expand All @@ -61,7 +63,8 @@ for (const retained of [1, 64, 1024])
group.writeFrame({ payload: new Uint8Array(3) });
group.writeFrame({ payload: new Uint8Array(4) });
group.close();
const received = (await baseline[0].recvGroup())!;
const received = await baseline[0].recvGroup();
if (!received) throw new Error("measured group missing");
await received.readFrame();
await received.readFrame();
received.close();
Expand Down
6 changes: 3 additions & 3 deletions js/net/src/connection/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,12 +348,12 @@ async function connectTransport(

try {
return await Promise.race([terminal, negotiate(url, session, wiring, setup)]);
} catch (cause) {
} catch (failure) {
// We refused the peer's SETUP and already closed with the code that says why.
if (cause instanceof ProtocolViolation) throw cause;
if (failure instanceof ProtocolViolation) throw failure;
// A session failure already guarantees a terminal close; its authoritative code
// must not be overwritten by the reset-only fallback while the browser delivers it.
cause = await sessionCause(session, cause);
const cause = await sessionCause(session, failure);
// A session shutdown can reject its SETUP stream before `closed` publishes the
// peer's close code. Wait briefly without closing locally, since a local clean close
// could overwrite that code. A reset-only peer is cleaned up after the grace period.
Expand Down
13 changes: 8 additions & 5 deletions js/net/src/lite/refresh.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,24 @@ test.each([ALPN_06, ALPN_07_WIP])("refresh joins reach a browser publisher on %s
while ((await announcements.next())?.kind !== "start") {}
const request = b.request(Path.from("room"));
while (request.active.peek() === undefined) await request.active.changed();
const remote = request.active.peek()!.track("data");
const active = request.active.peek();
if (!active) throw new Error("broadcast missing");
const remote = active.track("data");
expect((await remote.info()).refresh).toBe(alpn === ALPN_07_WIP ? 1 : undefined);
const baseline = remote.subscribe();
const group = producer.appendGroup();
group.writeFrame({ payload: new Uint8Array(3) });
group.writeFrame({ payload: new Uint8Array(3) });
const received = await baseline.recvGroup();
expect((await received!.readFrame())!.payload.length).toBe(3);
expect((await received!.readFrame())!.payload.length).toBe(3);
if (!received) throw new Error("group missing");
expect((await received.readFrame())?.payload.length).toBe(3);
expect((await received.readFrame())?.payload.length).toBe(3);
const joins = [remote.subscribe()];
await clock.advanceAsync(Nano(0));
expect(producer.demand().wanted.peek()).toBe(0);
updates.length = 0;
group.writeFrame({ payload: new Uint8Array(1) });
expect((await received!.readFrame())!.payload.length).toBe(1);
expect((await received.readFrame())?.payload.length).toBe(1);
for (let i = 0; i < 8; i++) joins.push(remote.subscribe());
await clock.advanceAsync(Nano(0));
if (alpn === ALPN_07_WIP) {
Expand All @@ -68,7 +71,7 @@ test.each([ALPN_06, ALPN_07_WIP])("refresh joins reach a browser publisher on %s
await clock.advanceAsync(Nano(0));
expect(updates).toEqual(alpn === ALPN_07_WIP ? [1, 1] : []);
for (const join of joins) join.close();
received!.close();
received.close();
baseline.close();
group.close();
} finally {
Expand Down
8 changes: 6 additions & 2 deletions js/net/src/priority.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,12 @@ test.each(["ascending", "descending"] as const)("a fill outranks its group's liv
priority.add(rest, 5, 2 ** 45);
priority.add(fill, 5, 0);
priority.add(other, order === "ascending" ? 4 : 6, Number.MAX_SAFE_INTEGER);
expect(streams[1].sendOrder).toBeGreaterThan(streams[0].sendOrder!);
expect(streams[2].sendOrder).toBeGreaterThan(streams[1].sendOrder!);
const [restOrder, fillOrder, otherOrder] = streams.map((stream) => {
if (stream.sendOrder === undefined) throw new Error("send order missing");
return stream.sendOrder;
});
expect(fillOrder).toBeGreaterThan(restOrder);
expect(otherOrder).toBeGreaterThan(fillOrder);
priority.remove(fill);
expect(streams[0].sendOrder).toBe(sendOrder({ priority: 7, position: 1 }));
priority.close();
Expand Down
2 changes: 1 addition & 1 deletion js/net/src/track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2225,7 +2225,7 @@ export class Subscriber {
}
for (let run = this.#pending.shift(); run; run = this.#pending.shift()) {
const dropped = report(run.start, run.end, run.error);
if (!dropped || dropped.kind !== "drop") continue;
if (dropped?.kind !== "drop") continue;
if (dropped.end < run.end)
this.#pending.unshift({ start: dropped.end, end: run.end, error: run.error });
return dropped;
Expand Down
14 changes: 7 additions & 7 deletions js/publish/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { resolve } from "path";
import { defineConfig } from "vite";
import { worklet } from "../common/vite-plugin-worklet";
import { lazyMedia } from "./bundle";
import { worklet } from "../common/vite-plugin-worklet.ts";
import { lazyMedia } from "./bundle.ts";

export default defineConfig({
plugins: [worklet(), lazyMedia()],
build: {
lib: {
entry: {
index: resolve(__dirname, "src/index.ts"),
element: resolve(__dirname, "src/element.ts"),
"ui/element": resolve(__dirname, "src/ui/element.ts"),
"support/index": resolve(__dirname, "src/support/index.ts"),
"support/element": resolve(__dirname, "src/support/element.ts"),
index: resolve(import.meta.dirname, "src/index.ts"),
element: resolve(import.meta.dirname, "src/element.ts"),
"ui/element": resolve(import.meta.dirname, "src/ui/element.ts"),
"support/index": resolve(import.meta.dirname, "src/support/index.ts"),
"support/element": resolve(import.meta.dirname, "src/support/element.ts"),
},
formats: ["es"],
},
Expand Down
12 changes: 6 additions & 6 deletions js/watch/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { resolve } from "path";
import { defineConfig } from "vite";
import { worklet } from "../common/vite-plugin-worklet";
import { worklet } from "../common/vite-plugin-worklet.ts";

export default defineConfig({
plugins: [worklet()],
build: {
lib: {
entry: {
index: resolve(__dirname, "src/index.ts"),
element: resolve(__dirname, "src/element.ts"),
"ui/element": resolve(__dirname, "src/ui/element.ts"),
"support/index": resolve(__dirname, "src/support/index.ts"),
"support/element": resolve(__dirname, "src/support/element.ts"),
index: resolve(import.meta.dirname, "src/index.ts"),
element: resolve(import.meta.dirname, "src/element.ts"),
"ui/element": resolve(import.meta.dirname, "src/ui/element.ts"),
"support/index": resolve(import.meta.dirname, "src/support/index.ts"),
"support/element": resolve(import.meta.dirname, "src/support/element.ts"),
},
formats: ["es"],
},
Expand Down
2 changes: 1 addition & 1 deletion py/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,4 @@ package:
docs:
rm -rf dist/docs
uv run --isolated --locked --only-group docs \
sphinx-build -b html moq-rs/docs dist/docs
sphinx-build -b html -W --keep-going moq-rs/docs dist/docs
14 changes: 8 additions & 6 deletions py/moq-rs/moq/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
MoqJsonValue,
)

from . import publish, subscribe
from ._records import _opt_from_us, _opt_us
from ._stream import _Stream
from .publish import BroadcastProducer, TrackDemand, TrackProducer
from .subscribe import TrackConsumer
from .publish import BroadcastProducer, TrackDemand

__all__ = ["SnapshotConsumer", "SnapshotProducer", "StreamConsumer", "StreamProducer", "Timed"]

Expand Down Expand Up @@ -63,7 +63,7 @@ class SnapshotProducer:
def __init__(
self,
broadcast: BroadcastProducer,
track: TrackProducer,
track: publish.TrackProducer,
*,
delta_ratio: int | None = None,
compression: bool = False,
Expand Down Expand Up @@ -97,7 +97,9 @@ class StreamProducer:
carries is refused.
"""

def __init__(self, broadcast: BroadcastProducer, track: TrackProducer, *, compression: bool = False) -> None:
def __init__(
self, broadcast: BroadcastProducer, track: publish.TrackProducer, *, compression: bool = False
) -> None:
config = MoqJsonStreamConfig(compression=compression)
self._inner = MoqJsonStreamProducer(broadcast._inner, track._inner, config)

Expand All @@ -123,7 +125,7 @@ class SnapshotConsumer(_Stream[Timed]):
context manager that cancels on exit.
"""

def __init__(self, track: TrackConsumer, *, compression: bool = False) -> None:
def __init__(self, track: subscribe.TrackConsumer, *, compression: bool = False) -> None:
# delta_ratio is producer-only, so leave it at its default here.
config = MoqJsonSnapshotConfig(compression=compression)
self._inner = MoqJsonSnapshotConsumer(track._inner, config)
Expand All @@ -150,7 +152,7 @@ class StreamConsumer(_Stream[Timed]):
async context manager that cancels on exit.
"""

def __init__(self, track: TrackConsumer, *, compression: bool = False) -> None:
def __init__(self, track: subscribe.TrackConsumer, *, compression: bool = False) -> None:
config = MoqJsonStreamConfig(compression=compression)
self._inner = MoqJsonStreamConsumer(track._inner, config)

Expand Down
11 changes: 6 additions & 5 deletions rs/moq-ffi/clippy.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# The wasm32 lint builds tokio without `time`, where these tokio paths do not resolve.
disallowed-methods = [
{ path = "std::time::Instant::now", reason = "read the ambient clock: moq_clock::now()" },
{ path = "std::time::SystemTime::now", reason = "read the ambient clock: moq_clock::wall()" },
{ path = "tokio::time::Instant::now", reason = "read the ambient clock: moq_clock::now()" },
{ path = "tokio::time::sleep", reason = "sleep on the ambient clock: moq_clock::sleep()" },
{ path = "tokio::time::sleep_until", reason = "sleep on the ambient clock: moq_clock::sleep_until()" },
{ path = "tokio::time::timeout", reason = "use the ambient clock: moq_clock::timeout()" },
{ path = "tokio::time::interval", reason = "use the ambient clock: moq_clock::interval()" },
{ path = "tokio::time::Instant::now", reason = "read the ambient clock: moq_clock::now()", allow-invalid = true },
{ path = "tokio::time::sleep", reason = "sleep on the ambient clock: moq_clock::sleep()", allow-invalid = true },
{ path = "tokio::time::sleep_until", reason = "sleep on the ambient clock: moq_clock::sleep_until()", allow-invalid = true },
{ path = "tokio::time::timeout", reason = "use the ambient clock: moq_clock::timeout()", allow-invalid = true },
{ path = "tokio::time::interval", reason = "use the ambient clock: moq_clock::interval()", allow-invalid = true },
]
11 changes: 6 additions & 5 deletions rs/moq-mux/clippy.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# The wasm32 lint builds tokio without `time`, where these tokio paths do not resolve.
disallowed-methods = [
{ path = "std::time::Instant::now", reason = "read the ambient clock: moq_clock::now()" },
{ path = "std::time::SystemTime::now", reason = "read the ambient clock: moq_clock::wall()" },
{ path = "tokio::time::Instant::now", reason = "read the ambient clock: moq_clock::now()" },
{ path = "tokio::time::sleep", reason = "sleep on the ambient clock: moq_clock::sleep()" },
{ path = "tokio::time::sleep_until", reason = "sleep on the ambient clock: moq_clock::sleep_until()" },
{ path = "tokio::time::timeout", reason = "use the ambient clock: moq_clock::timeout()" },
{ path = "tokio::time::interval", reason = "use the ambient clock: moq_clock::interval()" },
{ path = "tokio::time::Instant::now", reason = "read the ambient clock: moq_clock::now()", allow-invalid = true },
{ path = "tokio::time::sleep", reason = "sleep on the ambient clock: moq_clock::sleep()", allow-invalid = true },
{ path = "tokio::time::sleep_until", reason = "sleep on the ambient clock: moq_clock::sleep_until()", allow-invalid = true },
{ path = "tokio::time::timeout", reason = "use the ambient clock: moq_clock::timeout()", allow-invalid = true },
{ path = "tokio::time::interval", reason = "use the ambient clock: moq_clock::interval()", allow-invalid = true },
]
3 changes: 2 additions & 1 deletion sh/js/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ def scripts(verb):
finally:
Path(name).unlink()
# The fallback also covers unowned inputs, including demo/pub's Worker.
command("bun", "biome", "check", *(["js", "bench/browser", "test", "doc", "demo"] if plan["all"] else
# Recommended rules default to warn, which Biome otherwise lets pass.
command("bun", "biome", "check", "--error-on-warnings", *(["js", "bench/browser", "test", "doc", "demo"] if plan["all"] else
[p["directory"] for p in packages.values()] + ["js/common"]))
scripts("build")
for name in ("@moq/watch", "@moq/publish"):
Expand Down
Loading
Loading