-
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
,libmad
andlibmodplug
- Fix
sleef
build by usingfftw
as an alternative FFT backend - Fix
qttools
build (or figure out how to remove non-hostqttools
dependency fromqttranslations
)- Upstream issue: [qttools] Build error on wasm32-emscripten microsoft/vcpkg#37106
- Solution: We don't actually need
qttools
- Fix undefined
_qt_test_emscripten_version
inQt6WasmMacros.cmake
during 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
WrapRt
cannot be found when configuring Mixxx:Digging intoQt6Core could not be found because dependency WrapRt could not be found.
FindWrapRt.cmake
shows that thecheck_cxx_source_compiles
failed, which (asbuild/CMakeFiles/CMakeConfigureLog.yaml
revealed), failed due a missingclang-scan-deps
binary: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.
FindWrapRt
check).- 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)_FLAGS
does 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
PORTMIDI
flag for compiling with(out) PortMidi mixxxdj/mixxx#12913 - Build: Add
MUSICBRAINZ
flag for compiling with(out) MusicBrainz mixxxdj/mixxx#12914 - MixxxApplication: Use
QWasmIntegrationPlugin
when 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_ASSERTIONS
option mixxxdj/mixxx#12931 - VersionStore: Recognize Emscripten/WebAssembly mixxxdj/mixxx#12940
- CMakeLists: Fix deduplication trap with
--preload-file
mixxxdj/mixxx#12944 - OpenGLWindow: Fix sizing on Wasm by setting
Qt::FramelessWindowHint
mixxxdj/mixxx#12945 - CMakeLists: Require WebGL 2.0 when building for Wasm mixxxdj/mixxx#12952
- CoreServices: Default to
~/Music
as 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_t
check microsoft/vcpkg#37105 - [qtbase] Add
asyncify
feature 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
libid3tag
andlibmad
to!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.
IDBFS
to persist the.mixxx
directory - 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 TGZ
is used- Currently we get a desktop-like file structure with
bin
etc. - Instead we want a flat directory with
mixxx.{data,html,js,wasm,worker.js}
,qtloader.js
andqtlogo.svg
- From there,
emrun mixxx.html
can be used to launch the web app locally
- From there,
- Currently we get a desktop-like file structure with