-
Notifications
You must be signed in to change notification settings - Fork 8
Description
Status
The wasm branch contains experimental forks of mixxx and vcpkg for targeting wasm32-emscripten.
You can try it out, there is a GitHub Pages-hosted build at https://fwcd.github.io/m1xxx, but be warned: It may take a while to load (the Wasm binary is ~300 MB, the assets are ~90 MB) and there is no audio (the experimental "Web Audio" backend is not functional yet, hence why it is disabled by default).
On the technical side, there are still some major roadblocks to be resolved:
- Mixxx will crash when building with
-sASSERTIONS, see- This Qt forum post: https://forum.qt.io/topic/155159/cannot-have-multiple-async-operations-in-flight-at-once-during-qapplication-initialization
- This Emscripten issue: Embind causes "Cannot have multiple async operations in flight at once" assertion emscripten-core/emscripten#18412
- This Qt issue: https://bugreports.qt.io/browse/QTBUG-102827
- PortAudio is still lacking a Web Audio backend
- See Add support for Web Audio (Emscripten/WebAssembly) PortAudio/portaudio#887
- The interaction between Web Audio's asynchrony and Qt's issues with asynchrony seem to bring up some more issues: Feedback on AudioWorklets API emscripten-core/emscripten#18853 (comment)
- Given that we already have to build Mixxx without
-sASSERTIONS, any multiple in-flight async operations are effectively undefined behavior and manifest themselves in hard-to-debug failures at runtime (e.g. "unreachable" errors in the console, freezes, etc.) - Loading a track when the "Web Audio" backend is selected seems to also freeze the application, therefore it is disabled-by-default for now: fwcd/mixxx@21e45c5
- Given that we already have to build Mixxx without
Something to investigate would be whether we could replace -sASYNCIFY entirely with -sPROXY_TO_PTHREAD, i.e. move the "main" thread to a Web Worker where we can block synchronously. Unfortunately, there seem to be some complexities involved in making this work with Qt:
We may have to check whether setting USE_PTHREADS=1 for Qt would help here (or whether that would be redundant because our vcpkg triplet already sets -pthread).
Another option would be the recently-added C++20 co_await integration, which uses native LLVM coroutines and thus hopefully shouldn't be bound to the same limitations as Asyncify: emscripten-core/emscripten#20413
Given that PortAudio exposes a C interface, I am not sure how well we could integrate C++ coroutines there, however.
Motivation
Being able to run Mixxx on the web would be pretty cool. Qt supports WebAssembly, we would however also have to compile all of the other dependencies. This would probably take some work, but should not be impossible.
We take a similar approach to the iOS port (#16) and use custom WASM branches for mixxx and vcpkg, along with an integration branch in m1xxx, then gradually upstream the required changes.
Porting the dependencies to WebAssembly
- Configure Qt correctly with GL ES 3.0 and without
dbus - Fix
libflac,libmadandlibmodplug - Fix
sleefbuild by usingfftwas an alternative FFT backend - Fix
qttoolsbuild (or figure out how to remove non-hostqttoolsdependency fromqttranslations)- Upstream issue: [qttools] Build error on wasm32-emscripten microsoft/vcpkg#37106
- Solution: We don't actually need
qttools
- Fix undefined
_qt_test_emscripten_versioninQt6WasmMacros.cmakeduring Mixxx configure- Patched out in fwcd/vcpkg@e80fbb4, though we may want to look for a better solution before we attempt to upstream this
- Update Qt to 6.6.2
- This provides WASM stack traces in log messages and exceptions, which is really useful for debugging
Porting Mixxx to WebAssembly
- Figure out why
WrapRtcannot be found when configuring Mixxx:Digging intoQt6Core could not be found because dependency WrapRt could not be found.FindWrapRt.cmakeshows that thecheck_cxx_source_compilesfailed, which (asbuild/CMakeFiles/CMakeConfigureLog.yamlrevealed), failed due a missingclang-scan-depsbinary:Presumably we hit clang-scan-deps is required for CMake 3.28 C++ 20 module support emscripten-core/emscripten#21042, possibly because Mixxx uses C++20 (this would also explain why vcpkg builds of Qt passed, despite running the same"CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS-NOTFOUND" -format=p1689 -- /opt/emsdk/upstream/emscripten/em++ -DHAVE_STDATOMIC_WITH_LIB -fdiagnostics-color=auto -std=gnu++20 -x c++ /Users/fredrik/git/m1xxx-wasm/mixxx/build/CMakeFiles/CMakeScratch/TryCompile-QIjor4/src.cxx -c -o CMakeFiles/cmTC_0948e.dir/src.cxx.o -MT CMakeFiles/cmTC_0948e.dir/src.cxx.o.ddi -MD -MF CMakeFiles/cmTC_0948e.dir/src.cxx.o.ddi.d > CMakeFiles/cmTC_0948e.dir/src.cxx.o.ddi.tmp && mv CMakeFiles/cmTC_0948e.dir/src.cxx.o.ddi.tmp CMakeFiles/cmTC_0948e.dir/src.cxx.o.ddi /bin/sh: CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS-NOTFOUND: command not found ninja: build stopped: subcommand failed.FindWrapRtcheck).- Fix the problem (a704a27)
- Solve this linker error
The issue is likely that we have to compile (all?) our dependencies with
wasm-ld: error: --shared-memory is disallowed by sqlite3.c.o because it was not compiled with 'atomics' or 'bulk-memory' features.-pthread(as per this discussion). This should in principle be possible via the triplet, just settingVCPKG_C(XX)_FLAGSdoes not work, however:
How do I pass compiler/linker arguments to Emscripten? microsoft/vcpkg#30108- Fixed by introducing new triplets (
wasm32-emscripten-pthread(-release)) and settingset(ENV{EMCC_CFLAGS} "$ENV{EMCC_CFLAGS} -pthread")
- Fixed by introducing new triplets (
Upstreaming the Mixxx patches
- CMakeLists: Emit better errors for exotic target platforms mixxxdj/mixxx#12910
- Build: Add
PORTMIDIflag for compiling with(out) PortMidi mixxxdj/mixxx#12913 - Build: Add
MUSICBRAINZflag for compiling with(out) MusicBrainz mixxxdj/mixxx#12914 - MixxxApplication: Use
QWasmIntegrationPluginwhen targeting WebAssembly mixxxdj/mixxx#12915 - DesktopHelper: Compile out process-spawning on WASM too mixxxdj/mixxx#12916
- SSE: Check
!defined(__EMSCRIPTEN__)where intrinsics are unavailable on WASM mixxxdj/mixxx#12917 - CMakeLists: Add support for targeting Emscripten/WebAssembly mixxxdj/mixxx#12918
- CMakeLists: Enable asyncify when targeting WASM mixxxdj/mixxx#12921
- Resources: Bundle resources for preloading when targeting Emscripten/WASM mixxxdj/mixxx#12922
- WTrackMenu: Add missing wcoverartlabel.h include mixxxdj/mixxx#12924
- ScreenSaverHelper: Add no-op implementation for WASM mixxxdj/mixxx#12930
- CMakeLists: Add
WASM_ASSERTIONSoption mixxxdj/mixxx#12931 - VersionStore: Recognize Emscripten/WebAssembly mixxxdj/mixxx#12940
- CMakeLists: Fix deduplication trap with
--preload-filemixxxdj/mixxx#12944 - OpenGLWindow: Fix sizing on Wasm by setting
Qt::FramelessWindowHintmixxxdj/mixxx#12945 - CMakeLists: Require WebGL 2.0 when building for Wasm mixxxdj/mixxx#12952
- CoreServices: Default to
~/Musicas a music directory on Wasm and iOS mixxxdj/mixxx#13498 - ControllerRenderingEngine: Disable BGRA when targeting Wasm mixxxdj/mixxx#13502
Upstreaming the vcpkg patches
to microsoft/vcpkg
- [libflac] Fix WASM build by disabling stack protector via feature microsoft/vcpkg#37086
- [libmad] Fix WASM build by disabling asm-based optimizations microsoft/vcpkg#37088
- [libmodplug] Fix WASM build by pinning C++ standard to 11 microsoft/vcpkg#37090
- [rubberband] Use FFTW3 when targeting iOS or WASM microsoft/vcpkg#37101
- [soundtouch] Fix WASM build by using -O3 instead of -Ofast microsoft/vcpkg#37103
- [taglib] Fix WASM build by patching out
wchar_tcheck microsoft/vcpkg#37105 - [qtbase] Add
asyncifyfeature microsoft/vcpkg#37230
to mixxxdj/vcpkg
- [libflac] Fix WASM build by disabling stack protector via feature mixxxdj/vcpkg#134
- [libmad] Fix WASM build by disabling asm-based optimizations (#37088) mixxxdj/vcpkg#135
- [libmodplug] Fix WASM build by pinning C++ standard to 11 (#37090) mixxxdj/vcpkg#136
- [rubberband] Use FFTW3 when targeting iOS or WASM (#37101) mixxxdj/vcpkg#137
- [soundtouch] Fix WASM build by using -O3 instead of -Ofast (#37103) mixxxdj/vcpkg#138
- Scope
libid3tagandlibmadto!osx & !ios(to fix Wasm MP3 support) mixxxdj/vcpkg#139 - Add Emscripten/Wasm CI mixxxdj/vcpkg#140
- [icu] Cherry-pick Wasm fixes to 2.5 mixxxdj/vcpkg#141
TBD:
- Cherry-pick the PortAudio patches (Web Audio support)
- Cherry-pick the taglib patch, i.e. either rebase it or wait until Mixxx fully supports Taglib 2.0:
to upstream projects
Nice to have
- CI for Emscripten/WebAssembly
- GitHub Pages deployment: https://fwcd.github.io/m1xxx
- Support for local files/persistence
- See https://emscripten.org/docs/api_reference/Filesystem-API.html#filesystem-api-filesystems
- We could use e.g.
IDBFSto persist the.mixxxdirectory - For music, it would be best to let the user pick tracks from the host file system, if possible somehow
- Updating the install logic in CMakeLists to produce a proper archive when e.g.
cpack -G TGZis used- Currently we get a desktop-like file structure with
binetc. - Instead we want a flat directory with
mixxx.{data,html,js,wasm,worker.js},qtloader.jsandqtlogo.svg- From there,
emrun mixxx.htmlcan be used to launch the web app locally
- From there,
- Currently we get a desktop-like file structure with