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
34 changes: 30 additions & 4 deletions .github/actions/soluna/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ inputs:
description: 'The path to the Soluna repository. Defaults to .'
required: false
default: '.'
debug:
description: 'Whether to build Soluna in debug mode. Defaults to false.'
required: false
default: 'false'

outputs:
SOLUNA_BINARY:
Expand All @@ -20,6 +24,9 @@ outputs:
SOLUNA_JS_PATH:
description: 'The path to the Soluna JavaScript glue code for WebAssembly.'
value: ${{ steps.set-output.outputs.SOLUNA_JS_PATH }}
SOLUNA_WASM_MAP_PATH:
description: 'The path to the built Soluna WebAssembly map if debug is true.'
value: ${{ steps.set-output.outputs.SOLUNA_WASM_MAP_PATH }}

runs:
using: "composite"
Expand All @@ -35,7 +42,7 @@ runs:
id: cache
with:
path: ${{ inputs.soluna_path }}/bin
key: ${{ runner.os }}-soluna-build-${{ steps.refs.outputs.commit }}
key: ${{ runner.os }}-soluna-build-${{ steps.refs.outputs.commit }}-${{ inputs.debug }}
- name: Checkout all submodules
if: steps.cache.outputs.cache-hit != 'true'
working-directory: ${{ inputs.soluna_path }}
Expand All @@ -60,13 +67,23 @@ runs:
shell: powershell
working-directory: ${{ inputs.soluna_path }}
run: |
luamake soluna
if (${{ inputs.debug }} -eq 'true') {
$env:LUAMAKE_BUILD_TYPE = 'debug'
} else {
$env:LUAMAKE_BUILD_TYPE = 'release'
}
luamake -mode $env:LUAMAKE_BUILD_TYPE soluna
- name: Build (Unix)
if: runner.os != 'Windows' && steps.cache.outputs.cache-hit != 'true'
shell: bash
working-directory: ${{ inputs.soluna_path }}
run: |
luamake soluna
if [ "${{ inputs.debug }}" == "true" ]; then
export LUAMAKE_BUILD_TYPE=debug
else
export LUAMAKE_BUILD_TYPE=release
fi
luamake -mode $LUAMAKE_BUILD_TYPE soluna
- uses: mymindstorm/setup-emsdk@v14
if: runner.os == 'Linux' && steps.cache.outputs.cache-hit != 'true'
with:
Expand All @@ -77,7 +94,12 @@ runs:
working-directory: ${{ inputs.soluna_path }}
shell: bash
run: |
luamake -compiler emcc
if [ "${{ inputs.debug }}" == "true" ]; then
export LUAMAKE_BUILD_TYPE=debug
else
export LUAMAKE_BUILD_TYPE=release
fi
luamake -mode $LUAMAKE_BUILD_TYPE -compiler emcc
SOLUNA_JS="soluna.js"
SOLUNA_JS_PATH=$(find bin -name $SOLUNA_JS | head -n 1)
sed -i 's/setBindGroup(groupIndex,group,(growMemViews(),HEAPU32),dynamicOffsetsPtr>>2,dynamicOffsetCount)/setBindGroup(groupIndex,group,(growMemViews(),HEAPU32).subarray(dynamicOffsetsPtr>>2,(dynamicOffsetsPtr>>2)+dynamicOffsetCount))/g' "$SOLUNA_JS_PATH"
Expand All @@ -104,5 +126,9 @@ runs:
SOLUNA_JS_PATH=$(find $bin_dir -name "soluna.js" | head -n 1)
echo "SOLUNA_WASM_PATH=$SOLUNA_WASM_PATH" >> $GITHUB_OUTPUT
echo "SOLUNA_JS_PATH=$SOLUNA_JS_PATH" >> $GITHUB_OUTPUT
if [ "${{ inputs.debug }}" == "true" ]; then
SOLUNA_WASM_MAP_PATH=$(find $bin_dir -name "soluna.wasm.map" | head -n 1)
echo "SOLUNA_WASM_MAP_PATH=$SOLUNA_WASM_MAP_PATH" >> $GITHUB_OUTPUT
fi
fi
shell: bash
25 changes: 17 additions & 8 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ on:
branches:
- master
workflow_dispatch:
inputs:
debug:
description: 'Whether to build in debug mode'
required: false
default: 'false'

jobs:
build:
Expand All @@ -31,12 +36,13 @@ jobs:
id: build
with:
soluna_path: "."
debug: ${{ github.event.inputs.debug }}

- name: Build WASM side module (sample)
uses: ./.github/actions/sample
id: sample
with:
soluna_path: "."
# - name: Build WASM side module (sample)
# uses: ./.github/actions/sample
# id: sample
# with:
# soluna_path: "."

- name: Install web build tools
run: |
Expand All @@ -50,10 +56,13 @@ jobs:
--site web \
--wasm "${{ steps.build.outputs.SOLUNA_WASM_PATH }}" \
--js "${{ steps.build.outputs.SOLUNA_JS_PATH }}"
if [ -f "${{ steps.build.outputs.SOLUNA_WASM_MAP_PATH }}" ]; then
cp "${{ steps.build.outputs.SOLUNA_WASM_MAP_PATH }}" web/static/runtime/soluna.wasm.map
fi

- name: Copy WASM side module into runtime
run: |
cp "${{ steps.sample.outputs.SAMPLE_WASM_PATH }}" web/static/runtime/sample.wasm
# - name: Copy WASM side module into runtime
# run: |
# cp "${{ steps.sample.outputs.SAMPLE_WASM_PATH }}" web/static/runtime/sample.wasm

- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
Expand Down
16 changes: 8 additions & 8 deletions make.lua
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ lm:conf {
flags = {
"-Wall",
"-pthread",
"-fPIC",
"--use-port=emdawnwebgpu",
"-fwasm-exceptions",
},
links = {
"idbfs.js",
Expand All @@ -101,6 +101,12 @@ lm:conf {
"-s USE_PTHREADS=1",
"-s PTHREAD_POOL_SIZE='Math.max(2,navigator.hardwareConcurrency)'",
"-s PTHREAD_POOL_SIZE_STRICT=2",
"-s AUDIO_WORKLET=1",
"-s WASM_WORKERS=1",
"-s JSPI",
"-fwasm-exceptions",
lm.mode == "debug" and "-gsource-map",
lm.mode == "debug" and "-s EXCEPTION_STACK_TRACES=1",
lm.mode == "debug" and "-s ASSERTIONS=2",
-- lm.mode == "debug" and "-s SAFE_HEAP=1",
lm.mode == "debug" and "-s STACK_OVERFLOW_CHECK=1",
Expand All @@ -109,6 +115,7 @@ lm:conf {
defines = {
"_POSIX_C_SOURCE=200809L",
"_GNU_SOURCE",
"MA_ENABLE_AUDIO_WORKLETS",
},
},
defines = {
Expand All @@ -132,13 +139,6 @@ lm:import "clibs/soluna/make.lua"

lm:exe "soluna" {
deps = deps,
emcc = {
ldflags = {
"-s MAIN_MODULE=1",
"-Wl,-u,emscripten_builtin_memalign",
"-Wl,--export=emscripten_builtin_memalign",
},
},
}

lm:dll "sample" {
Expand Down
16 changes: 1 addition & 15 deletions script/build_web.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@ local function run(cmd)
end
end

local function read_file(path)
local f = assert(io.open(path, "rb"))
local data = f:read("*a")
f:close()
return data
end

local function write_file(path, data)
local f = assert(io.open(path, "wb"))
f:write(data)
Expand Down Expand Up @@ -116,13 +109,6 @@ local function shortcode_quote(value)
return value:gsub("\\", "\\\\"):gsub("\"", "\\\"")
end

local function html_escape(value)
return value
:gsub("&", "&")
:gsub("<", "&lt;")
:gsub(">", "&gt;")
end

local function write_front_matter(lines, fields)
lines[#lines + 1] = "---"
for _, field in ipairs(fields) do
Expand Down Expand Up @@ -324,7 +310,7 @@ local example_paths = exec_lines("find " .. shell_quote(soluna_dir .. "/test") .
table.sort(example_paths)
for _, path in ipairs(example_paths) do
local name = path:match("([^/]+)%.lua$")
if name then
if name and name ~= "extlua" then
examples[#examples + 1] = {
id = name,
title = titleize(name),
Expand Down
48 changes: 48 additions & 0 deletions src/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

#include "zipreader.h"

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif

#define MA_NO_WIN32_FILEIO
#define MA_NO_MP3
#define MA_NO_FLAC
Expand Down Expand Up @@ -54,6 +58,47 @@ struct custom_engine {
struct custom_vfs vfs;
};

#if defined(__EMSCRIPTEN__)
EM_JS(void, soluna_webaudio_resume_on_gesture, (int audio_context), {
if (typeof document === "undefined") return;
try {
const ctx = emscriptenGetAudioObject(audio_context);
if (!ctx || typeof ctx.resume !== "function") return;
const resume = () => {
if (ctx.state === "running") return;
const p = ctx.resume();
if (p && typeof p.catch === "function") {
p.catch((err) => console.error("Failed to resume AudioContext", err));
}
};
["pointerdown", "touchstart", "touchend", "keydown", "click"].forEach((event_type) => {
document.addEventListener(event_type, resume, { once: true, capture: true });
});
} catch (err) {
console.error("Failed to install WebAudio resume handler", err);
}
});

static void
inject_webaudio_resume(struct ma_engine *engine) {
ma_device *device;
if (engine == NULL) {
return;
}
device = ma_engine_get_device(engine);
if (device == NULL || device->pContext == NULL) {
return;
}
if (device->pContext->backend != ma_backend_webaudio) {
return;
}
if (device->webaudio.audioContext == 0) {
return;
}
soluna_webaudio_resume_on_gesture(device->webaudio.audioContext);
}
#endif

static ma_result
zr_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile) {
struct custom_vfs *vfs = (struct custom_vfs *)pVFS;
Expand Down Expand Up @@ -165,6 +210,9 @@ laudio_init(lua_State *L) {
if (r != MA_SUCCESS) {
return luaL_error(L, "ma_engine_init() error : %s", ma_result_description(r));
}
#if defined(__EMSCRIPTEN__)
inject_webaudio_resume(&e->engine);
#endif
lua_pushlightuserdata(L, (void *)e);

return 2;
Expand Down
Loading
Loading