Skip to content

Conversation

@mccartyp
Copy link

@mccartyp mccartyp commented Jan 26, 2026

Summary

Addresses #15741

This introduces a full REST API server for Mixxx, enabling external applications to query and control the DJ software over HTTP/HTTPS.

  • REST API server built on Qt HttpServer with versioned endpoints (/api/v1/) for controlling decks, playlists, AutoDJ, and mixer state. Supports bulk commands (207 multi-status aggregation), Server-Sent Events streaming for real-time status updates, and a /api/v1/schema discovery endpoint.
  • Authentication and TLS: Scoped token-based auth with read/write permissions, auto-generated self-signed TLS certificates for HTTPS, CORS allowlist, and enforced TLS for write-capable tokens.
  • Preferences UI: New REST API page in Preferences with token management (create, copy, show/hide toggle), TLS configuration with certificate info and regeneration, listener address/port settings, and contextual tooltips and helper text.
  • Qt cross-version compatibility: Version guards for QJsonArray::reserve (Qt 6.9+/6.11+), QDateTime::setTimeZone, QHttpServer bind return types, and QHttpHeaders migration across Qt 5 and Qt 6.x.

New and modified files (23 files, ~3000+ lines)

REST API Core (src/network/rest/)

File Description
restapigateway.cpp/.h API gateway handling all REST endpoints (~1200 lines)
restserver.cpp/.h HTTP/HTTPS server with TLS support
restservercontroller.cpp/.h Server lifecycle management
restservervalidator.cpp/.h Request validation and HTTPS capability checks
certificategenerator.cpp/.h Self-signed TLS certificate generation
restscopes.h Token scope definitions
README.md API endpoint documentation

Preferences & Settings

File Description
src/preferences/dialog/dlgprefrestserver.cpp/.h Preferences dialog
src/preferences/dialog/dlgprefrestserverdlg.ui Qt Designer UI layout
src/preferences/restserversettings.cpp/.h REST server settings persistence

Integration, Utilities, Assets

File Description
src/coreservices.cpp/.h REST server integration into Mixxx startup
src/util/ratelimitedlogger.cpp/.h Rate-limited logging utility
src/test/restserver_test.cpp REST API unit tests
res/images/preferences/*/ic_preferences_rest_api.svg Dark/light theme icons
CMakeLists.txt REST API build targets
res/mixxx.qrc Resource file updated with new icons

…rences

Add REST API preference icon and use it in preferences dialog
…up-cmake

Guard QJsonArray::reserve for Qt5 compatibility
…up-cmake

Guard QJsonArray/QStringList `reserve()` calls for Qt5 compatibility
…up-cmake

Guard reserve() calls for Qt5 and older-Qt6 compatibility
…up-cmake

Guard reserve() calls for Qt 5 and older Qt6 compatibility
…sage

Fix constness of parent passed to QFileDialog in REST server prefs
…sage

Fix UTC handling in REST server prefs
…qt-http-server

Handle Qt6 HttpServer dependencies and add detailed discovery logging
…ter-and-trackid

Add track includes to REST API gateway header
…-usage

Migrate REST server to QHttpHeaders and update QHttpServerResponse overloads
…alls-for-qt-compatibility

Update QtHttpServer API usage in REST server
…array

Wrap REST header values in QByteArray before trimming
…in-restserver.cpp

Guard QJsonArray::reserve with Qt 6.9 version check
…aptures

Capture REST route helpers in route lambdas
mccartyp and others added 21 commits January 27, 2026 20:08
…-yeWP3

Fix clazy warnings in restserver.cpp that break the build
The fonts-ubuntu package is referenced in Debian Trixie's package
database but has no installation candidate. The previous check using
`apt-cache show` returned success for such packages, causing apt-get
install to fail with exit code 100.

Replace the check with `apt-cache policy` which can distinguish between
packages that have an actual installation candidate and those that are
merely referenced. Also fix the stderr redirect typo `2>%1` -> `2>&1`
in the mold/lld availability checks.

https://claude.ai/code/session_01Susz5ZsD7VpQMopUMNHyVe
…Aq3dC

Fix Debian Trixie build failure due to fonts-ubuntu package check
Add `// namespace` comment to the closing brace of the anonymous
namespace in restapigateway.cpp to satisfy the
google-readability-namespace-comments clang-tidy check.

https://claude.ai/code/session_012HBQkpq9rCazP2SLqJXzEA
Fix anonymous namespace missing closing comment warning
Qt 6.8 removed QAbstractHttpServer::sslSetup() and setSslConfiguration().
TLS is now configured by creating a QSslServer, setting its SSL
configuration, making it listen, and binding it to the HTTP server via
QAbstractHttpServer::bind(). Both existing compile checks tested for
the removed methods, causing TLS detection to fail on Qt 6.8.2 (Debian
13/Trixie) and Qt 6.9.2 (Ubuntu 25.10).

Changes:
- CMakeLists.txt: Add third compile check for QSslServer + bind()
  approach. Also filter INTERFACE_INCLUDE_DIRECTORIES to remove
  NOTFOUND values and unresolved generator expressions that could
  interfere with try_compile.
- restserver.cpp: Add startWithSslServerBind() method that creates a
  QSslServer, configures TLS, listens on it, and binds it to the HTTP
  server. startOnThread() uses this path when MIXXX_HAS_HTTP_SERVER_TLS_BIND_API
  is defined.
- restserver.h: Declare startWithSslServerBind() private method.
- restservervalidator.cpp: Include MIXXX_HAS_HTTP_SERVER_TLS_BIND_API
  in TLS support detection.

https://claude.ai/code/session_015tAvtdkc1q3wTzwdC2AAEz
Fix TLS detection for Qt 6.8+ HttpServer (Ubuntu 25.10, Debian 13)
Qt 6.8+ changed the HttpServer router to require QHttpServerResponder
to be passed as an lvalue reference (QHttpServerResponder&) instead of
an rvalue reference (QHttpServerResponder&&). Use a version conditional
to select the correct parameter type, fixing build failures on Ubuntu
24.10 and Debian 13.

https://claude.ai/code/session_01EnHXkvCpMhKsaSTcFCGdfe
Fix QHttpServerResponder parameter type for Qt 6.8+ builds
Qt-generated QSB resource files contain binary shader data that triggers
a crash in Clang 18's lexer (Lexer::SkipWhitespace during
SkipExcludedConditionalBlock). This causes the rendergraph_sg_resources_1
target to fail compilation when CXX is set to clazy.

Skip qt6_add_shaders for both rendergraph_sg and rendergraph_gl targets
when the compiler is clazy, since clazy builds only perform static
analysis and don't need the compiled shader resources.

https://claude.ai/code/session_01LC3wTmvGsJMWcBh1WXvwWM
Skip qt6_add_shaders when building with clazy to avoid Clang 18 crash
Reorganize the tool for better usability:
- Reformat usage comments at top into organized sections (General,
  Connection & Basic Checks, Deck Control, Playlists, AutoDJ, Advanced)
- Group argparse arguments into logical categories (Connection, Check
  Selection, Output, Deck Control, AutoDJ, Playlists, Advanced)
- Add --demo flag for interactive demonstration mode designed for video
  capture, which runs 8 numbered steps through both HTTP and HTTPS:
  health check, status, list playlists, load playlist to AutoDJ,
  enable AutoDJ, play, stop, and replace AutoDJ queue

https://claude.ai/code/session_018m4kXcMgV1e12uFpez8uf3
Add infer_checks_from_args() function that automatically determines which
checks to run based on provided arguments:

- --play-deck, --pause-deck, --control → infers 'control' check
- --autodj-enable → infers 'autodj_write' check
- --playlist-action → infers 'playlists' check
- --playlist-read-id → infers 'playlists_read' check

This allows simplified usage without explicit --check flags:
  python3 tools/rest_api_test.py --play-deck 1
  python3 tools/rest_api_test.py --autodj-enable
  python3 tools/rest_api_test.py --playlist-read-id 12

Update documentation examples to reflect the simplified usage.

https://claude.ai/code/session_018m4kXcMgV1e12uFpez8uf3
…buntu-for-debian-13

Gate Ubuntu font dependency to Ubuntu-derived systems
…t-hooks

style: format Qt HttpServer CMake logic
@mccartyp
Copy link
Author

Hello sir,

Thanks for the request — I’ve added a couple of short demo videos to show the REST API in use. The first video below demonstrates the API from the command line using a small scripted sequence of requests, showing request/response behavior and direct interaction with Mixxx state.

The second video shows integration with the Bitfocus Companion ecosystem using a development module (https://github.com/mccartyp/companion-module-mixxx). Companion integration is particularly relevant in event production environments, as it enables flexible, distributed control of Mixxx via Stream Deck hardware (https://www.elgato.com/en/stream-deck). For context, Bitfocus Companion provides a large ecosystem of integrations for audio, lighting, video, and control systems commonly used in live production, with a public module directory at https://bitfocus.io/companion. I plan to submit the Mixxx Companion module referenced above for inclusion in the distribution if the REST API is eventually merged and available for users.

I’ll be rebasing this PR shortly as I've had to refactor some of the code to ensure compatibility with earlier Qt versions (< 6.5.0). The changes have now been tested on Ubuntu 24.04 and Debian 13/Trixie. Please let me know if you’d like to see additional endpoints or scenarios demonstrated or have any feedback on the effort itself. No doubt there is much room for improvement.

Lastly, I’ve also included several screenshots of the Preferences dialog highlighting how the REST API is configured and enabled.

Thanks,
Patrick

Mixxx REST API Demo Video

Mixxx-Ubuntu_24.04.mp4

Mixxx REST API Demo Video with Companion

Mixxx-Ubuntu_24.04_Companion.mp4

Mixxx REST API Preferences

Mixxx-REST-Preferences-1 Mixxx-REST-Preferences-2

@bigpresh
Copy link

This is brilliant!

This is one thing I've been really missing and wanting from Mixxx.

One use case I have in mind is a karaoke setup - a script watching Mixxx status, and, if a karoke track begins to play on either deck and a .cdg file with a matching name is found, causing VLC on a second screen to start playing that and ensure the timestamps stay roughly in sync (using VLC's API)

I've done some initial testing on my Ubuntu 24.04 box using a recent build from the Actions build workflow and it appears to be working nicely so far - I've not exercised it hard so far though and not yet tested controlling Mixxx through it, only watching status e.g. GET /api/v1/status etc.

I think this will be a very powerful feature for Mixxx, opening up lots of useful integrations.

@mccartyp
Copy link
Author

@bigpresh Glad it's useful for you. For your use case instead of polling via GET /api/v1/status, you might consider attaching to the SSE endpoint GET /api/v1/stream/status, which is a persistent stream of events and updates, as described in the README in the /src/network/rest directory:

  • GET /api/v1/stream/status — server-sent events stream that emits status deltas at the configured interval. Requires status:read. Each event uses event: status and a JSON payload in data: containing only changed top-level fields since the last update (removed fields are sent as null). The first event includes the full status payload.

…-remove-dialog

Remove Web Server preferences dialog (moved to REST API page)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build code quality developer experience Issues, bugs and PRs related to the development process, development environment & developer docs packaging preferences ui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants