Files
workinf_Blender_Wasm/web/protocol/sequencer-audio-session.ts
mes123456 0fe8d2bb56
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
Advance M8-M11 parity workflows
2026-08-17 04:37:07 -04:00

87 lines
4.1 KiB
TypeScript

import type { ErrorCode } from "./error";
export const SEQUENCER_AUDIO_SESSION_SCHEMA = 1 as const;
export type SequencerAudioContextState = "UNAVAILABLE" | "SUSPENDED" | "RUNNING" | "CLOSED";
export type SequencerAudioOutputState = "BLOCKED" | "SILENT" | "ENABLED";
export type SequencerAudioSessionIssueCode = Extract<
ErrorCode,
| "SEQUENCER_AUDIO_DEVICE_UNAVAILABLE"
| "SEQUENCER_AUDIO_RESUME_FAILED"
| "SEQUENCER_AUDIO_SUSPEND_FAILED"
>;
export interface SequencerAudioSessionReportIR {
schemaVersion: typeof SEQUENCER_AUDIO_SESSION_SCHEMA;
revision: number;
contextState: SequencerAudioContextState;
outputState: SequencerAudioOutputState;
muted: boolean;
outputGain: number;
issueCode: SequencerAudioSessionIssueCode | null;
}
export class SequencerAudioSessionValidationError extends Error {
readonly code: ErrorCode;
constructor(message: string) {
super(`SEQUENCER_AUDIO_CONTEXT_INVALID: ${message}`);
this.name = "SequencerAudioSessionValidationError";
this.code = "SEQUENCER_AUDIO_CONTEXT_INVALID";
}
}
const REPORT_KEYS = new Set([
"schemaVersion", "revision", "contextState", "outputState", "muted", "outputGain", "issueCode",
]);
const CONTEXT_STATES = new Set<SequencerAudioContextState>(["UNAVAILABLE", "SUSPENDED", "RUNNING", "CLOSED"]);
const OUTPUT_STATES = new Set<SequencerAudioOutputState>(["BLOCKED", "SILENT", "ENABLED"]);
const ISSUE_CODES = new Set<SequencerAudioSessionIssueCode>([
"SEQUENCER_AUDIO_DEVICE_UNAVAILABLE",
"SEQUENCER_AUDIO_RESUME_FAILED",
"SEQUENCER_AUDIO_SUSPEND_FAILED",
]);
function record(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
export function parseSequencerAudioSessionReport(value: unknown): SequencerAudioSessionReportIR {
if (!record(value) || value.schemaVersion !== SEQUENCER_AUDIO_SESSION_SCHEMA ||
Object.keys(value).length !== REPORT_KEYS.size || Object.keys(value).some((key) => !REPORT_KEYS.has(key))) {
throw new SequencerAudioSessionValidationError("audio session report fields are invalid");
}
if (!Number.isSafeInteger(value.revision) || (value.revision as number) < 0 ||
!CONTEXT_STATES.has(value.contextState as SequencerAudioContextState) ||
!OUTPUT_STATES.has(value.outputState as SequencerAudioOutputState) ||
typeof value.muted !== "boolean" || typeof value.outputGain !== "number" ||
!Number.isFinite(value.outputGain) || value.outputGain < 0 || value.outputGain > 1 ||
(value.issueCode !== null && !ISSUE_CODES.has(value.issueCode as SequencerAudioSessionIssueCode))) {
throw new SequencerAudioSessionValidationError("audio session report values are invalid");
}
const report = value as unknown as SequencerAudioSessionReportIR;
if (report.contextState === "UNAVAILABLE" &&
(report.outputState !== "BLOCKED" || report.outputGain !== 0 ||
report.issueCode !== "SEQUENCER_AUDIO_DEVICE_UNAVAILABLE")) {
throw new SequencerAudioSessionValidationError("unavailable audio context must be blocked");
}
if (report.contextState === "CLOSED" &&
(report.outputState !== "SILENT" || report.outputGain !== 0 || report.issueCode !== null)) {
throw new SequencerAudioSessionValidationError("closed audio context must release output");
}
if ((report.contextState === "RUNNING" || report.contextState === "SUSPENDED") && report.outputState === "BLOCKED") {
throw new SequencerAudioSessionValidationError("an allocated audio context cannot report blocked output");
}
if (report.contextState === "SUSPENDED" && report.outputState !== "SILENT") {
throw new SequencerAudioSessionValidationError("a suspended audio context must be silent");
}
if (report.outputState === "ENABLED" &&
(report.contextState !== "RUNNING" || report.muted || report.outputGain <= 0 || report.issueCode !== null)) {
throw new SequencerAudioSessionValidationError("enabled audio output invariants are invalid");
}
if (report.muted && report.outputGain !== 0) {
throw new SequencerAudioSessionValidationError("muted audio output gain must be zero");
}
return { ...report };
}