Mixxx C++ Development
Build & Test
bash# Build (IMMER -j4, nie mehr!) CC=/usr/bin/gcc CXX=/usr/bin/g++ cmake --build build -j4 # Nur Library (schneller) CC=/usr/bin/gcc CXX=/usr/bin/g++ cmake --build build -j4 --target mixxx-lib # Tests CC=/usr/bin/gcc CXX=/usr/bin/g++ cmake --build build -j4 --target mixxx-test ./build/mixxx-test --gtest_filter="*Beat*:*Bar*"
Architecture Patterns
Waveform Rendering
Zwei Rendering-Backends:
| Backend | Base class | Drawing |
|---|---|---|
| allshader | rendergraph::GeometryNode | GPU geometry nodes, textures |
| legacy | WaveformRendererAbstract | QPainter on QPaintEvent |
allshader renderers (src/waveform/renderers/allshader/):
- Inherit from
GeometryNode(notNode) preprocess()runs each frame; enable withsetUsePreprocess(true)UniColorMaterialfor solid colors,TextureMaterialfor text/images
Legacy renderers (src/waveform/renderers/):
- Override
draw(QPainter*, QPaintEvent*) QLineFvectors +painter->drawLines()
Beat System
src/track/beats.h— ImmutableBeatsclass (viashared_ptr<const Beats>)BeatMarkervector + last marker position/BPM- Beat-to-bar:
globalBeatIndex = it - trackBeats->cfirstmarker() - Downbeat:
((globalBeatIndex % beatsPerBar) + beatsPerBar) % beatsPerBar == 0 - Mutations return
std::optional<BeatsPointer>(new immutable copy)
Per-track time signature:
Beats::beatsPerBar()— 0 = "nicht erkannt", Renderer fällt auf globale Einstellung zurückBeats::downbeatOffset()— 0 = Standard-AnkertrySetBeatsPerBar(int)/trySetDownbeatOffset(int)— Mutation-Methoden- Bestehende Mutations preserven beide Felder
Renderer-Fallback-Pattern:
cppconst int beatsPerBar = (m_pTrackBeats && m_pTrackBeats->beatsPerBar() > 0) ? m_pTrackBeats->beatsPerBar() : m_beatsPerBar; // globale WaveformWidgetFactory-Einstellung
Protobuf Serialization
src/proto/beats.proto— BeatGrid and BeatMap messages- New fields must be
optionalfor backward compatibility - BeatGrid:
bpm,first_beat,beats_per_bar,downbeat_offset - BeatMap:
beat(repeated),beats_per_bar,downbeat_offset const_caston freshly-createdBeatsPointeris safe for setting fields after construction
Analyzer Pipeline
AnalyzerBeatsPluginbase →AnalyzerQueenMaryBeats(QM-DSP)- QM-DSP
DownBeatclass for time signature detection (multi-candidate bpb 3-7) AnalyzerBeats::storeResults()→BeatFactory::makePreferredBeats()→ Track
Track Properties Dialog
- BPM tab:
spinBeatsPerBarQSpinBox, range 0-32, 0="Auto" - Load:
reloadTrackBeats(), Save:saveTrack()viatrySetBeatsPerBar() - Disabled when BPM locked
Code Style Quick Reference
| Element | Convention |
|---|---|
| Braces | Same-line (Google style) |
| Members | m_camelCase, pointers m_pCamelCase |
| Constants | kPascalCase |
| Strings | QStringLiteral("...") |
| Enums | enum class only |
| Memory | std::make_unique / std::make_shared / make_parented |
| Guards | #pragma once |
| Overrides | override always, no redundant virtual |
| Signals | Direct method pointer connects preferred over lambdas |
| Formatting | clang-format; only format touched code |


