cef7619833
Make the Emscripten build behave like the desktop app for loading, window scaling, and exporting. All changes are #ifdef __EMSCRIPTEN__-gated or no-op on desktop, so native behavior is unchanged. Scaling: - Drop FLAG_WINDOW_HIGHDPI on web. The emscripten-GLFW shim forces a fixed pixel canvas style (!important) when HiDPI-aware, overriding the shell's 100vw/100vh CSS so the canvas can't fill the page; raylib's own resize/window callbacks also disagree about dividing by devicePixelRatio, desyncing the framebuffer from the reported screen size. - Sync raylib's window size to window.innerWidth/innerHeight each frame via SetWindowSize (guarded against no-op churn). This keeps screen size, GL viewport, and projection consistent, so the UI fills the viewport and reflows on resize like the desktop window. Loading: - Compute the full-resolution STFT synchronously when a file loads instead of the desktop overview-then-deferred-high-res path, which relied on many main-loop iterations yielding to the browser and appeared to stall partway. - Allow the wasm heap to grow (INITIAL_MEMORY + ALLOW_MEMORY_GROWTH) so longer recordings fit now that everything is computed up front. Exports: - Add Platform_OfferFileToUser(): no-op on desktop (file is already on disk); on web it reads the just-written file from MEMFS and triggers a browser download, then unlinks the temp copy. Wired into PNG and WAV export, which now show just the filename in the status message. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
96 lines
3.1 KiB
C
96 lines
3.1 KiB
C
/*
|
|
* platform_web.c — Emscripten/WebAssembly stub implementation
|
|
*
|
|
* The web version cannot spawn child processes, so these functions
|
|
* return "not supported". A real implementation would use Emscripten's
|
|
* pthreads or asyncify if ffmpeg integration is needed.
|
|
*/
|
|
|
|
#include "platform.h"
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <errno.h> /* ENOSYS */
|
|
#include <emscripten.h> /* EM_ASM */
|
|
|
|
/* ── Helpers ─────────────────────────────────────────────────────────── */
|
|
|
|
static char last_error_msg[256] = { 0 };
|
|
|
|
static void set_last_error(const char *fmt, ...) {
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
vsnprintf(last_error_msg, sizeof(last_error_msg), fmt, args);
|
|
va_end(args);
|
|
}
|
|
|
|
/* ── Platform API ────────────────────────────────────────────────────── */
|
|
|
|
PlatformError Platform_SpawnChild(const char *program, const char **argv,
|
|
PlatformSpawnHandle *out_handle) {
|
|
(void)program;
|
|
(void)argv;
|
|
set_last_error("Spawning child processes is not supported on the web");
|
|
out_handle->last_error = ENOSYS;
|
|
return PLATFORM_NOT_SUPPORTED;
|
|
}
|
|
|
|
PlatformError Platform_WaitForChild(PlatformSpawnHandle *handle) {
|
|
(void)handle;
|
|
return PLATFORM_NOT_SUPPORTED;
|
|
}
|
|
|
|
SpawnStatus Platform_GetExitStatus(const PlatformSpawnHandle *handle, int *code) {
|
|
(void)handle;
|
|
(void)code;
|
|
return SPAWN_WAITING;
|
|
}
|
|
|
|
void Platform_CloseSpawnHandle(PlatformSpawnHandle *handle) {
|
|
if (!handle) return;
|
|
handle->handle = NULL;
|
|
handle->status = SPAWN_WAITING;
|
|
handle->exit_code = 0;
|
|
handle->last_error = 0;
|
|
}
|
|
|
|
const char *Platform_GetLastErrorMessage(void) {
|
|
return last_error_msg;
|
|
}
|
|
|
|
const char *Platform_GetTempDir(void) {
|
|
/*
|
|
* Emscripten's virtual filesystem: "/" works as root.
|
|
* For persistent downloads/uploads, consider IDBFS mount.
|
|
*/
|
|
return "/";
|
|
}
|
|
|
|
void Platform_OfferFileToUser(const char *path) {
|
|
if (!path) return;
|
|
/*
|
|
* The file was just written into the in-memory (MEMFS) filesystem, which
|
|
* the user can't see. Read it back and hand it to the browser as a
|
|
* download, then unlink the temporary copy so we don't leak heap memory.
|
|
*/
|
|
EM_ASM({
|
|
var p = UTF8ToString($0);
|
|
try {
|
|
var data = FS.readFile(p); // Uint8Array
|
|
var name = p.split('/').pop() || 'download';
|
|
var blob = new Blob([data], { type: 'application/octet-stream' });
|
|
var url = URL.createObjectURL(blob);
|
|
var a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = name;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
document.body.removeChild(a);
|
|
setTimeout(function() { URL.revokeObjectURL(url); }, 1000);
|
|
try { FS.unlink(p); } catch (e) {}
|
|
} catch (e) {
|
|
console.error('rspektrum: download failed for ' + p + ': ' + e);
|
|
}
|
|
}, path);
|
|
}
|