From 51e996db72e66cffa6eef72834094ff5ae3a5832 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sat, 24 Aug 2024 23:17:51 -0700 Subject: [PATCH] remove unmaintained WASM support Same reasoning as outlined in #1254 > nobody is interested in actively maintaining or contributing to that today. Signed-off-by: Stephen Gutekanst --- .github/workflows/m1_ci.yml | 5 +- build.zig | 2 - src/core/Timer.zig | 3 +- src/core/wasm/Timer.zig | 25 -- src/core/wasm/entrypoint.zig | 42 --- src/core/wasm/js.zig | 42 --- src/core/wasm/mach.js | 569 ----------------------------------- src/gfx/font/main.zig | 11 +- src/sysaudio/backends.zig | 12 - src/sysaudio/webaudio.zig | 275 ----------------- 10 files changed, 7 insertions(+), 979 deletions(-) delete mode 100644 src/core/wasm/Timer.zig delete mode 100644 src/core/wasm/entrypoint.zig delete mode 100644 src/core/wasm/js.zig delete mode 100644 src/core/wasm/mach.js delete mode 100644 src/sysaudio/webaudio.zig diff --git a/.github/workflows/m1_ci.yml b/.github/workflows/m1_ci.yml index 4ce34c041a..0f53ee25de 100644 --- a/.github/workflows/m1_ci.yml +++ b/.github/workflows/m1_ci.yml @@ -26,5 +26,6 @@ jobs: run: zig build test - name: build run: zig build - - name: build (WASM) - run: zig build -Dtarget=wasm32-freestanding-none + # TODO: get WASM builds working + # - name: build (WASM) + # run: zig build -Dtarget=wasm32-freestanding-none diff --git a/build.zig b/build.zig index 06884b1505..d22c7cd058 100644 --- a/build.zig +++ b/build.zig @@ -372,7 +372,6 @@ fn buildExamples( core: bool = false, name: []const u8, deps: []const Dependency = &.{}, - wasm: bool = false, has_assets: bool = false, }{ // Mach core examples @@ -388,7 +387,6 @@ fn buildExamples( .{ .name = "sprite", .deps = &.{ .zigimg, .assets } }, .{ .name = "text", .deps = &.{.assets} }, }) |example| { - if (target.result.cpu.arch == .wasm32 and !example.wasm) continue; const exe = b.addExecutable(.{ .name = if (example.core) b.fmt("core-{s}", .{example.name}) else example.name, .root_source_file = if (example.core) diff --git a/src/core/Timer.zig b/src/core/Timer.zig index f74ddf3ace..820fd59e92 100644 --- a/src/core/Timer.zig +++ b/src/core/Timer.zig @@ -1,7 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const WasmTimer = @import("wasm/Timer.zig"); -const PlatformTimer = if (builtin.cpu.arch == .wasm32) WasmTimer else NativeTimer; +const PlatformTimer = if (builtin.cpu.arch == .wasm32) @panic("TODO: support WASM") else NativeTimer; const Timer = @This(); diff --git a/src/core/wasm/Timer.zig b/src/core/wasm/Timer.zig deleted file mode 100644 index ee833a5122..0000000000 --- a/src/core/wasm/Timer.zig +++ /dev/null @@ -1,25 +0,0 @@ -const std = @import("std"); -const js = @import("js.zig"); - -pub const Timer = @This(); - -initial: f64 = undefined, - -pub fn start() !Timer { - return Timer{ .initial = js.machPerfNow() }; -} - -pub fn read(timer: *Timer) u64 { - return @intFromFloat((js.machPerfNow() - timer.initial) * std.time.ns_per_ms); -} - -pub fn reset(timer: *Timer) void { - timer.initial = js.machPerfNow(); -} - -pub fn lap(timer: *Timer) u64 { - const now = js.machPerfNow(); - const initial = timer.initial; - timer.initial = now; - return @as(u64, @intFromFloat(now - initial)) * std.time.ns_per_ms; -} diff --git a/src/core/wasm/entrypoint.zig b/src/core/wasm/entrypoint.zig deleted file mode 100644 index 47c9ee095f..0000000000 --- a/src/core/wasm/entrypoint.zig +++ /dev/null @@ -1,42 +0,0 @@ -// Check that the user's app matches the required interface. -comptime { - if (!@import("builtin").is_test) @import("mach").core.AppInterface(@import("app")); -} - -// Forward "app" declarations into our namespace, such that @import("root").foo works as expected. -pub usingnamespace @import("app"); -const App = @import("app").App; - -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -var app: App = undefined; -export fn wasmInit() void { - App.init(&app) catch |err| @panic(@errorName(err)); -} - -export fn wasmUpdate() bool { - if (core.update(&app) catch |err| @panic(@errorName(err))) { - return true; - } - return false; -} - -export fn wasmDeinit() void { - app.deinit(); -} - -// Define std_options.logFn if the user did not in their "app" main.zig -pub usingnamespace if (@hasDecl(App, "std_options")) struct {} else struct { - pub const std_options = std.Options{ - .logFn = core.defaultLog, - }; -}; - -// Define panic() if the user did not in their "app" main.zig -pub usingnamespace if (@hasDecl(App, "panic")) struct {} else struct { - pub const panic = core.defaultPanic; -}; diff --git a/src/core/wasm/js.zig b/src/core/wasm/js.zig deleted file mode 100644 index 68777be1d0..0000000000 --- a/src/core/wasm/js.zig +++ /dev/null @@ -1,42 +0,0 @@ -pub const CanvasId = u32; - -pub extern "mach" fn machLogWrite(str: [*]const u8, len: u32) void; -pub extern "mach" fn machLogFlush() void; -pub extern "mach" fn machPanic(str: [*]const u8, len: u32) void; - -pub extern "mach" fn machCanvasInit(selector_id: *u8) CanvasId; -pub extern "mach" fn machCanvasDeinit(canvas: CanvasId) void; -pub extern "mach" fn machCanvasFramebufferWidth(canvas: CanvasId) u32; -pub extern "mach" fn machCanvasFramebufferHeight(canvas: CanvasId) u32; -pub extern "mach" fn machCanvasSetTitle(canvas: CanvasId, title: [*]const u8, len: u32) void; -pub extern "mach" fn machCanvasSetDisplayMode(canvas: CanvasId, mode: u32) void; -pub extern "mach" fn machCanvasDisplayMode(canvas: CanvasId) u32; -pub extern "mach" fn machCanvasSetBorder(canvas: CanvasId, value: bool) void; -pub extern "mach" fn machCanvasBorder(canvas: CanvasId) bool; -pub extern "mach" fn machCanvasSetHeadless(canvas: CanvasId, value: bool) void; -pub extern "mach" fn machCanvasHeadless(canvas: CanvasId) bool; -pub extern "mach" fn machCanvasSetVsync(canvas: CanvasId, mode: u32) void; -pub extern "mach" fn machCanvasVsync(canvas: CanvasId) u32; -pub extern "mach" fn machCanvasSetSize(canvas: CanvasId, width: u32, height: u32) void; -pub extern "mach" fn machCanvasWidth(canvas: CanvasId) u32; -pub extern "mach" fn machCanvasHeight(canvas: CanvasId) u32; -pub extern "mach" fn machCanvasSetSizeLimit(canvas: CanvasId, min_width: i32, min_height: i32, max_width: i32, max_height: i32) void; -pub extern "mach" fn machCanvasMinWidth(canvas: CanvasId) u32; -pub extern "mach" fn machCanvasMinHeight(canvas: CanvasId) u32; -pub extern "mach" fn machCanvasMaxWidth(canvas: CanvasId) u32; -pub extern "mach" fn machCanvasMaxHeight(canvas: CanvasId) u32; -pub extern "mach" fn machSetCursorMode(canvas: CanvasId, mode: u32) void; -pub extern "mach" fn machCursorMode(canvas: CanvasId) u32; -pub extern "mach" fn machSetCursorShape(canvas: CanvasId, shape: u32) void; -pub extern "mach" fn machCursorShape(canvas: CanvasId) u32; -pub extern "mach" fn machJoystickName(idx: u8, dest: [*:0]u8, dest_len: usize) void; -pub extern "mach" fn machJoystickButtons(idx: u8, dest: [*]u8, dest_len: usize) void; -pub extern "mach" fn machJoystickAxes(idx: u8, dest: [*]f32, dest_len: usize) void; - -pub extern "mach" fn machShouldClose() bool; -pub extern "mach" fn machHasEvent() bool; -pub extern "mach" fn machEventShift() i32; -pub extern "mach" fn machEventShiftFloat() f64; -pub extern "mach" fn machChangeShift() u32; - -pub extern "mach" fn machPerfNow() f64; diff --git a/src/core/wasm/mach.js b/src/core/wasm/mach.js deleted file mode 100644 index 33f88c4948..0000000000 --- a/src/core/wasm/mach.js +++ /dev/null @@ -1,569 +0,0 @@ -const text_decoder = new TextDecoder(); -const text_encoder = new TextEncoder(); - -const mach = { - canvases: [], - wasm: undefined, - observer: undefined, - events: [], - changes: [], - log_buf: "", - - init(wasm) { - mach.wasm = wasm; - mach.observer = new MutationObserver((mutables) => { - mutables.forEach((mutable) => { - mach.canvases.forEach((canvas) => { - if (mutable.target == canvas) { - if (mutable.attributeName === "width" || - mutable.attributeName === "height" || - mutable.attributeName === "style") { - mutable.target.dispatchEvent(new Event("mach-canvas-resize")); - } - } - }); - }) - }) - }, - - getString(str, len) { - const memory = mach.wasm.exports.memory.buffer; - return text_decoder.decode(new Uint8Array(memory, str, len)); - }, - - setString(str, buf) { - const memory = mach.wasm.exports.memory.buffer; - const strbuf = text_encoder.encode(str); - const outbuf = new Uint8Array(memory, buf, strbuf.length); - for (let i = 0; i < strbuf.length; i += 1) { - outbuf[i] = strbuf[i]; - } - }, - - machLogWrite(str, len) { - mach.log_buf += mach.getString(str, len); - }, - - machLogFlush() { - console.log(mach.log_buf); - mach.log_buf = ""; - }, - - machPanic(str, len) { - throw Error(mach.getString(str, len)); - }, - - machCanvasInit(id) { - let canvas = document.createElement("canvas"); - canvas.id = "#mach-canvas-" + mach.canvases.length; - canvas.style.border = "1px solid"; - canvas.style.position = "absolute"; - canvas.style.display = "block"; - canvas.tabIndex = 1; - - mach.observer.observe(canvas, { attributes: true }); - - mach.setString(canvas.id, id); - - canvas.addEventListener("contextmenu", (ev) => ev.preventDefault()); - - canvas.addEventListener("keydown", (ev) => { - if (ev.repeat) { - mach.events.push(...[EventCode.key_repeat, convertKeyCode(ev.code)]); - } else { - mach.events.push(...[EventCode.key_press, convertKeyCode(ev.code)]); - } - }); - - canvas.addEventListener("keyup", (ev) => { - mach.events.push(...[EventCode.key_release, convertKeyCode(ev.code)]); - }); - - canvas.addEventListener("mousemove", (ev) => { - mach.events.push(...[EventCode.mouse_motion, ev.clientX, ev.clientY]); - }); - - canvas.addEventListener("mousedown", (ev) => { - mach.events.push(...[EventCode.mouse_press, ev.button]); - }); - - canvas.addEventListener("mouseup", (ev) => { - mach.events.push(...[EventCode.mouse_release, ev.button]); - }); - - canvas.addEventListener("wheel", (ev) => { - mach.events.push(...[EventCode.mouse_scroll, ev.deltaX, ev.deltaY]); - }); - - canvas.addEventListener("gamepadconnected", (ev) => { - mach.events.push(...[ - EventCode.joystick_connected, ev.gamepad.index, - ev.gamepad.buttons.length, ev.gamepad.axes.length, - ]); - }); - - canvas.addEventListener("gamepaddisconnected", (ev) => { - mach.events.push(...[EventCode.joystick_disconnected, ev.gamepad.index]); - }); - - canvas.addEventListener("mach-canvas-resize", (ev) => { - const cv_index = mach.canvases.findIndex((el) => el === ev.currentTarget); - const cv = mach.canvases[cv_index]; - mach.events.push(...[EventCode.framebuffer_resize, cv.width, cv.height, window.devicePixelRatio]); - }); - - canvas.addEventListener("focus", (ev) => { - mach.events.push(...[EventCode.focus_gained]); - }); - - canvas.addEventListener("blur", (ev) => { - mach.events.push(...[EventCode.focus_lost]); - }); - - document.body.appendChild(canvas); - return mach.canvases.push(canvas) - 1; - }, - - machCanvasDeinit(canvas) { - if (mach.canvases[canvas] != undefined) { - mach.canvases.splice(canvas, 1); - } - }, - - machCanvasFramebufferWidth(canvas) { - const cv = mach.canvases[canvas]; - return cv.width; - }, - - machCanvasFramebufferHeight(canvas) { - const cv = mach.canvases[canvas]; - return cv.height; - }, - - machCanvasSetTitle(canvas, title, len) { - // TODO(wasm) - }, - - machCanvasSetDisplayMode(canvas, mode) { - const cv = mach.canvases[canvas]; - switch (mode) { - case DisplayMode.windowed: - document.exitFullscreen(); - break; - case DisplayMode.fullscreen: - cv.requestFullscreen(); - break; - } - }, - - machCanvasDisplayMode(canvas) { - if (mach.canvases[canvas].fullscreenElement == null) { - return DisplayMode.windowed; - } else { - return DisplayMode.fullscreen; - } - }, - - machCanvasSetBorder(canvas, value) { - // TODO(wasm) - }, - - machCanvasBorder(canvas) { - // TODO(wasm) - }, - - machCanvasSetHeadless(canvas, value) { - // TODO(wasm) - }, - - machCanvasHeadless(canvas) { - // TODO(wasm) - }, - - machCanvasSetVSync(canvas, mode) { - // TODO(wasm) - }, - - machCanvasVSync(canvas) { - // TODO(wasm) - }, - - machCanvasSetSize(canvas, width, height) { - const cv = mach.canvases[canvas]; - if (width > 0 && height > 0) { - cv.style.width = width + "px"; - cv.style.height = height + "px"; - cv.width = Math.floor(width * window.devicePixelRatio); - cv.height = Math.floor(height * window.devicePixelRatio); - } - }, - - machCanvasWidth(canvas) { - const cv = mach.canvases[canvas]; - return cv.width / window.devicePixelRatio; - }, - - machCanvasHeight(canvas) { - const cv = mach.canvases[canvas]; - return cv.height / window.devicePixelRatio; - }, - - machCanvasSetSizeLimit(canvas, min_width, min_height, max_width, max_height) { - const cv = mach.canvases[canvas]; - if (min_width == -1) { - cv.style.minWidth = "inherit" - } else { - cv.style.minWidth = min_width + "px"; - } - if (min_width == -1) { - cv.style.minHeight = "inherit" - } else { - cv.style.minHeight = min_height + "px"; - } - if (min_width == -1) { - cv.style.maxWidth = "inherit" - } else { - cv.style.maxWidth = max_width + "px"; - } - if (min_width == -1) { - cv.style.maxHeight = "inherit" - } else { - cv.style.maxHeight = max_height + "px"; - } - }, - - machCanvasMinWidth(canvas) { - const cv = mach.canvases[canvas]; - return cv.style.minWidth; - }, - - machCanvasMinHeight(canvas) { - const cv = mach.canvases[canvas]; - return cv.style.minHeight; - }, - - machCanvasMaxWidth(canvas) { - const cv = mach.canvases[canvas]; - return cv.style.maxWidth; - }, - - machCanvasMaxHeight(canvas) { - const cv = mach.canvases[canvas]; - return cv.style.maxHeight; - }, - - machSetCursorMode(canvas, mode) { - const cv = mach.canvases[canvas]; - switch (mode) { - case CursorMode.normal: - cv.style.cursor = 'default'; - break; - case CursorMode.hidden: - cv.style.cursor = 'none'; - break; - case CursorMode.hidden: - cv.style.cursor = 'none'; - break; - } - }, - - machCursorMode(canvas) { - switch (mach.canvases[canvas].style.cursor) { - case 'none': return CursorMode.hidden; - default: return CursorMode.normal; - } - }, - - machSetCursorShape(canvas, shape) { - const cv = mach.canvases[canvas]; - switch (shape) { - case CursorShape.arrow: - cv.style.cursor = 'default'; - break; - case CursorShape.ibeam: - cv.style.cursor = 'text'; - break; - case CursorShape.crosshair: - cv.style.cursor = 'crosshair'; - break; - case CursorShape.pointing_hand: - cv.style.cursor = 'pointer'; - break; - case CursorShape.resize_ew: - cv.style.cursor = 'ew-resize'; - break; - case CursorShape.resize_ns: - cv.style.cursor = 'ns-resize'; - break; - case CursorShape.resize_nwse: - cv.style.cursor = 'nwse-resize'; - break; - case CursorShape.resize_nesw: - cv.style.cursor = 'nesw-resize'; - break; - case CursorShape.resize_all: - cv.style.cursor = 'move'; - break; - case CursorShape.not_allowed: - cv.style.cursor = 'not-allowed'; - break; - } - }, - - machCursorShape(canvas) { - switch (mach.canvases[canvas].style.cursor) { - case 'default': return CursorShape.arrow; - case 'text': return CursorShape.ibeam; - case 'crosshair': return CursorShape.crosshair; - case 'pointer': return CursorShape.pointing_hand; - case 'ew-resize': return CursorShape.resize_ew; - case 'ns-resize': return CursorShape.resize_ns; - case 'nwse-resize': return CursorShape.resize_nwse; - case 'nesw-resize': return CursorShape.resize_nesw; - case 'move': return CursorShape.resize_all; - case 'not-allowed': return CursorShape.not_allowed; - } - }, - - machJoystickName(idx, dest, dest_len) { - const gamepads = navigator.getGamepads(); - - if( idx < 0 || idx > gamepads.length ) - return; - - if( gamepads[idx] === null || gamepads[idx] === undefined ) - return; - - const name = gamepads[idx].id; - const strbuf = text_encoder.encode(name).slice(0, dest_len); - const dstbuf = new Uint8Array(mach.wasm.exports.memory.buffer, dest, dest_len+1); - dstbuf.set(strbuf); - dstbuf[dest_len] = 0; - }, - - machJoystickButtons(idx, dest, dest_len) { - const gamepads = navigator.getGamepads(); - - if( idx < 0 || idx > gamepads.length ) - return; - - if( gamepads[idx] === null || gamepads[idx] === undefined ) - return; - - const buttons = gamepads[idx].buttons.map(x => x.pressed ? 1 : 0); - const count = Math.min(dest_len, buttons.length); - const dstbuf = new Uint8Array(mach.wasm.exports.memory.buffer, dest, count); - dstbuf.set(buttons); - }, - - machJoystickAxes(idx, dest, dest_len) { - const gamepads = navigator.getGamepads(); - - if( idx < 0 || idx > gamepads.length ) - return; - - if( gamepads[idx] === null || gamepads[idx] === undefined ) - return; - - const axes = gamepads[idx].axes; - const count = Math.min(dest_len, axes.length); - const dstbuf = new Float32Array(mach.wasm.exports.memory.buffer, dest, count); - dstbuf.set(axes); - }, - - machHasEvent() { - return mach.events.length > 0; - }, - - machEventShift() { - if (mach.machHasEvent()) - return mach.events.shift(); - - return -1; - }, - - machEventShiftFloat() { - return mach.machEventShift(); - }, - - machPerfNow() { - return performance.now(); - }, -}; - -function convertKeyCode(code) { - const k = Key[code]; - if (k != undefined) - return k; - return 118; // Unknown -} - -const EventCode = { - key_press: 0, - key_repeat: 1, - key_release: 2, - char_input: 3, - mouse_motion: 4, - mouse_press: 5, - mouse_release: 6, - mouse_scroll: 7, - joystick_connected: 8, - joystick_disconnected: 9, - framebuffer_resize: 10, - focus_gained: 11, - focus_lost: 12, - close: 13, -}; - -const Key = { - KeyA: 0, - KeyB: 1, - KeyC: 2, - KeyD: 3, - KeyE: 4, - KeyF: 5, - KeyG: 6, - KeyH: 7, - KeyI: 8, - KeyJ: 9, - KeyK: 10, - KeyL: 11, - KeyM: 12, - KeyN: 13, - KeyO: 14, - KeyP: 15, - KeyQ: 16, - KeyR: 17, - KeyS: 18, - KeyT: 19, - KeyU: 20, - KeyV: 21, - KeyW: 22, - KeyX: 23, - KeyY: 24, - KeyZ: 25, - - Digit0: 26, - Digit1: 27, - Digit2: 28, - Digit3: 29, - Digit4: 30, - Digit5: 31, - Digit6: 32, - Digit7: 33, - Digit8: 34, - Digit9: 35, - - F1: 36, - F2: 37, - F3: 38, - F4: 39, - F5: 40, - F6: 41, - F7: 42, - F8: 43, - F9: 44, - F10: 45, - F11: 46, - F12: 47, - F13: 48, - F14: 49, - F15: 50, - F16: 51, - F17: 52, - F18: 53, - F19: 54, - F20: 55, - F21: 56, - F22: 57, - F23: 58, - F24: 59, - F25: 60, - - NumpadDivide: 61, - NumpadMultiply: 62, - NumpadSubtract: 63, - NumpadAdd: 64, - Numpad0: 65, - Numpad1: 66, - Numpad2: 67, - Numpad3: 68, - Numpad4: 69, - Numpad5: 70, - Numpad6: 71, - Numpad7: 72, - Numpad8: 73, - Numpad9: 74, - NumpadDecimal: 75, - NumpadEqual: 76, - NumpadEnter: 77, - - Enter: 78, - Escape: 79, - Tab: 80, - ShiftLeft: 81, - ShiftRight: 82, - ControlLeft: 83, - ControlRight: 84, - AltLeft: 85, - AltRight: 86, - OSLeft: 87, - MetaLeft: 87, - OSRight: 88, - MetaRight: 88, - ContextMenu: 89, - NumLock: 90, - CapsLock: 91, - PrintScreen: 92, - ScrollLock: 93, - Pause: 94, - Delete: 95, - Home: 96, - End: 97, - PageUp: 98, - PageDown: 99, - Insert: 100, - ArrowLeft: 101, - ArrowRight: 102, - ArrowUp: 103, - ArrowDown: 104, - Backspace: 105, - Space: 106, - Minus: 107, - Equal: 108, - BracketLeft: 109, - BracketRight: 110, - Backslash: 111, - Semicolon: 112, - Quote: 113, - Comma: 114, - Period: 115, - Slash: 116, - Backquote: 117, -}; - -const DisplayMode = { - windowed: 0, - fullscreen: 1, -}; - -const CursorMode = { - normal: 0, - hidden: 1, - disabled: 2, -}; - -const CursorShape = { - arrow: 0, - ibeam: 1, - crosshair: 2, - pointing_hand: 3, - resize_ew: 4, - resize_ns: 5, - resize_nwse: 6, - resize_nesw: 7, - resize_all: 8, - not_allowed: 9, -}; - -export { mach }; diff --git a/src/gfx/font/main.zig b/src/gfx/font/main.zig index 91cb6c511f..ff7fd608a3 100644 --- a/src/gfx/font/main.zig +++ b/src/gfx/font/main.zig @@ -5,14 +5,9 @@ const math = mach.math; const vec2 = math.vec2; const Vec2 = math.Vec2; -pub const Font = FontInterface(if (@import("builtin").cpu.arch == .wasm32) { - @panic("TODO: implement wasm/Font.zig"); -} else @import("native/Font.zig")); - -pub const TextRun = TextRunInterface(if (@import("builtin").cpu.arch == .wasm32) -{ - @panic("TODO: implement wasm/TextRun.zig"); -} else @import("native/TextRun.zig")); +pub const Font = FontInterface(if (@import("builtin").cpu.arch == .wasm32) @panic("TODO: implement wasm/Font.zig") else @import("native/Font.zig")); + +pub const TextRun = TextRunInterface(if (@import("builtin").cpu.arch == .wasm32) @panic("TODO: implement wasm/TextRun.zig") else @import("native/TextRun.zig")); fn FontInterface(comptime T: type) type { assertDecl(T, "initBytes", fn (font_bytes: []const u8) anyerror!T); diff --git a/src/sysaudio/backends.zig b/src/sysaudio/backends.zig index 71e4283b0d..89f3af218c 100644 --- a/src/sysaudio/backends.zig +++ b/src/sysaudio/backends.zig @@ -26,10 +26,6 @@ pub const Context = switch (builtin.os.tag) { dummy: *@import("dummy.zig").Context, }, .freestanding => switch (builtin.cpu.arch) { - .wasm32 => union(enum) { - webaudio: *@import("webaudio.zig").Context, - dummy: *@import("dummy.zig").Context, - }, else => union(enum) { dummy: *@import("dummy.zig").Context, }, @@ -60,10 +56,6 @@ pub const Player = switch (builtin.os.tag) { dummy: *@import("dummy.zig").Player, }, .freestanding => switch (builtin.cpu.arch) { - .wasm32 => union(enum) { - webaudio: *@import("webaudio.zig").Player, - dummy: *@import("dummy.zig").Player, - }, else => union(enum) { dummy: *@import("dummy.zig").Player, }, @@ -94,10 +86,6 @@ pub const Recorder = switch (builtin.os.tag) { dummy: *@import("dummy.zig").Recorder, }, .freestanding => switch (builtin.cpu.arch) { - .wasm32 => union(enum) { - webaudio: *@import("webaudio.zig").Recorder, - dummy: *@import("dummy.zig").Recorder, - }, else => union(enum) { dummy: *@import("dummy.zig").Recorder, }, diff --git a/src/sysaudio/webaudio.zig b/src/sysaudio/webaudio.zig deleted file mode 100644 index 6ea30fc79e..0000000000 --- a/src/sysaudio/webaudio.zig +++ /dev/null @@ -1,275 +0,0 @@ -const std = @import("std"); -const js = @import("sysjs"); -const main = @import("main.zig"); -const backends = @import("backends.zig"); -const util = @import("util.zig"); - -const default_sample_rate = 44_100; // Hz -const channel_size = 1024; -const channel_size_bytes = channel_size * @sizeOf(f32); - -const default_playback = main.Device{ - .id = "default-playback", - .name = "Default Device", - .mode = .playback, - .channels = undefined, - .formats = &.{.f32}, - .sample_rate = .{ - .min = 8_000, - .max = 96_000, - }, -}; - -pub const Context = struct { - allocator: std.mem.Allocator, - devices_info: util.DevicesInfo, - - pub fn init(allocator: std.mem.Allocator, options: main.Context.Options) !backends.Context { - _ = options; - - const audio_context = js.global().get("AudioContext"); - if (audio_context.is(.undefined)) - return error.ConnectionRefused; - - const ctx = try allocator.create(Context); - errdefer allocator.destroy(ctx); - ctx.* = .{ - .allocator = allocator, - .devices_info = util.DevicesInfo.init(), - }; - - return .{ .webaudio = ctx }; - } - - pub fn deinit(ctx: *Context) void { - for (ctx.devices_info.list.items) |d| - freeDevice(ctx.allocator, d); - ctx.devices_info.list.deinit(ctx.allocator); - ctx.allocator.destroy(ctx); - } - - pub fn refresh(ctx: *Context) !void { - for (ctx.devices_info.list.items) |d| - freeDevice(ctx.allocator, d); - ctx.devices_info.clear(); - - try ctx.devices_info.list.append(ctx.allocator, default_playback); - ctx.devices_info.list.items[0].channels = try ctx.allocator.alloc(main.ChannelPosition, 2); - ctx.devices_info.list.items[0].channels[0] = .front_left; - ctx.devices_info.list.items[0].channels[1] = .front_right; - ctx.devices_info.setDefault(.playback, 0); - } - - pub fn devices(ctx: Context) []const main.Device { - return ctx.devices_info.list.items; - } - - pub fn defaultDevice(ctx: Context, mode: main.Device.Mode) ?main.Device { - return ctx.devices_info.default(mode); - } - - pub fn createPlayer(ctx: *Context, device: main.Device, writeFn: main.WriteFn, options: main.StreamOptions) !backends.Player { - const context_options = js.createMap(); - defer context_options.deinit(); - context_options.set("sampleRate", js.createNumber(options.sample_rate orelse default_sample_rate)); - - const audio_context = js.constructType("AudioContext", &.{context_options.toValue()}); - const gain_node = audio_context.call("createGain", &.{ - js.createNumber(1), - js.createNumber(0), - js.createNumber(device.channels.len), - }).view(.object); - const process_node = audio_context.call("createScriptProcessor", &.{ - js.createNumber(channel_size), - js.createNumber(device.channels.len), - }).view(.object); - - const player = try ctx.allocator.create(Player); - errdefer ctx.allocator.destroy(player); - - var captures = try ctx.allocator.alloc(js.Value, 1); - captures[0] = js.createNumber(@intFromPtr(player)); - - const document = js.global().get("document").view(.object); - defer document.deinit(); - const click_event_str = js.createString("click"); - defer click_event_str.deinit(); - const resume_on_click = js.createFunction(Player.resumeOnClick, captures); - _ = document.call("addEventListener", &.{ click_event_str.toValue(), resume_on_click.toValue() }); - - const audio_process_event = js.createFunction(Player.audioProcessEvent, captures); - defer audio_process_event.deinit(); - process_node.set("onaudioprocess", audio_process_event.toValue()); - - player.* = .{ - .allocator = ctx.allocator, - .audio_context = audio_context, - .process_node = process_node, - .gain_node = gain_node, - .process_captures = captures, - .resume_on_click = resume_on_click, - .buf = try ctx.allocator.alloc(u8, channel_size_bytes * device.channels.len), - .buf_js = js.constructType("Uint8Array", &.{js.createNumber(channel_size_bytes)}), - .is_paused = false, - .writeFn = writeFn, - .user_data = options.user_data, - .channels = device.channels, - .format = .f32, - .sample_rate = options.sample_rate orelse default_sample_rate, - }; - - return .{ .webaudio = player }; - } - - pub fn createRecorder(ctx: *Context, device: main.Device, readFn: main.ReadFn, options: main.StreamOptions) !backends.Recorder { - _ = readFn; - const recorder = try ctx.allocator.create(Recorder); - recorder.* = .{ - .allocator = ctx.allocator, - .is_paused = false, - .vol = 1.0, - .channels = device.channels, - .format = options.format, - .sample_rate = options.sample_rate orelse default_sample_rate, - }; - return .{ .webaudio = recorder }; - } -}; - -pub const Player = struct { - allocator: std.mem.Allocator, - audio_context: js.Object, - process_node: js.Object, - gain_node: js.Object, - process_captures: []js.Value, - resume_on_click: js.Function, - buf: []u8, - buf_js: js.Object, - is_paused: bool, - writeFn: main.WriteFn, - user_data: ?*anyopaque, - - channels: []main.ChannelPosition, - format: main.Format, - sample_rate: u24, - - pub fn deinit(player: *Player) void { - player.resume_on_click.deinit(); - player.buf_js.deinit(); - player.gain_node.deinit(); - player.process_node.deinit(); - player.audio_context.deinit(); - player.allocator.free(player.process_captures); - player.allocator.free(player.buf); - player.allocator.destroy(player); - } - - pub fn start(player: *Player) !void { - const destination = player.audio_context.get("destination").view(.object); - defer destination.deinit(); - _ = player.gain_node.call("connect", &.{destination.toValue()}); - _ = player.process_node.call("connect", &.{player.gain_node.toValue()}); - } - - fn resumeOnClick(args: js.Object, _: usize, captures: []js.Value) js.Value { - const player = @as(*Player, @ptrFromInt(@as(usize, @intFromFloat(captures[0].view(.num))))); - player.play() catch {}; - - const document = js.global().get("document").view(.object); - defer document.deinit(); - - const event = args.getIndex(0).view(.object); - defer event.deinit(); - _ = document.call("removeEventListener", &.{ event.toValue(), player.resume_on_click.toValue() }); - - return js.createUndefined(); - } - - fn audioProcessEvent(args: js.Object, _: usize, captures: []js.Value) js.Value { - const player = @as(*Player, @ptrFromInt(@as(usize, @intFromFloat(captures[0].view(.num))))); - - const event = args.getIndex(0).view(.object); - defer event.deinit(); - const output_buffer = event.get("outputBuffer").view(.object); - defer output_buffer.deinit(); - - player.writeFn(player.user_data, player.buf[0..channel_size]); - - for (player.channels, 0..) |_, i| { - player.buf_js.copyBytes(player.buf[i * channel_size_bytes .. (i + 1) * channel_size_bytes]); - const buf_f32_js = js.constructType("Float32Array", &.{ player.buf_js.get("buffer"), player.buf_js.get("byteOffset"), js.createNumber(channel_size) }); - defer buf_f32_js.deinit(); - _ = output_buffer.call("copyToChannel", &.{ buf_f32_js.toValue(), js.createNumber(i) }); - } - - return js.createUndefined(); - } - - pub fn play(player: *Player) !void { - _ = player.audio_context.call("resume", &.{js.createUndefined()}); - player.is_paused = false; - } - - pub fn pause(player: *Player) !void { - _ = player.audio_context.call("suspend", &.{js.createUndefined()}); - player.is_paused = true; - } - - pub fn paused(player: *Player) bool { - return player.is_paused; - } - - pub fn setVolume(player: *Player, vol: f32) !void { - const gain = player.gain_node.get("gain").view(.object); - defer gain.deinit(); - gain.set("value", js.createNumber(vol)); - } - - pub fn volume(player: *Player) !f32 { - const gain = player.gain_node.get("gain").view(.object); - defer gain.deinit(); - return @as(f32, @floatCast(gain.get("value").view(.num))); - } -}; - -pub const Recorder = struct { - allocator: std.mem.Allocator, - is_paused: bool, - vol: f32, - - channels: []main.ChannelPosition, - format: main.Format, - sample_rate: u24, - - pub fn deinit(recorder: *Recorder) void { - recorder.allocator.destroy(recorder); - } - - pub fn start(recorder: *Recorder) !void { - _ = recorder; - } - - pub fn record(recorder: *Recorder) !void { - recorder.is_paused = false; - } - - pub fn pause(recorder: *Recorder) !void { - recorder.is_paused = true; - } - - pub fn paused(recorder: *Recorder) bool { - return recorder.is_paused; - } - - pub fn setVolume(recorder: *Recorder, vol: f32) !void { - recorder.vol = vol; - } - - pub fn volume(recorder: *Recorder) !f32 { - return recorder.vol; - } -}; - -fn freeDevice(allocator: std.mem.Allocator, device: main.Device) void { - allocator.free(device.channels); -}