VirtualDJ Rust SDK
A complete Rust binding for the VirtualDJ Plugin SDK, enabling developers to write VirtualDJ plugins entirely in Rust while maintaining full compatibility with the C++ ABI.
Architecture
This SDK consists of three layers:
┌─────────────────────────────────────────────┐
│ User Rust Plugin (Pure Rust) │
│ - Implements plugin traits │
│ - No C++ knowledge required │
└────────────────┬────────────────────────────┘
│ (Safe abstraction)
┌────────────────▼────────────────────────────┐
│ Rust Safe API (rs_core/lib.rs) │
│ - Trait definitions (DspPlugin, etc) │
│ - Error handling (PluginError) │
│ - High-level abstractions │
└────────────────┬────────────────────────────┘
│ (FFI bindings)
┌────────────────▼────────────────────────────┐
│ Rust FFI Layer (rs_core/ffi.rs) │
│ - Raw C function declarations │
│ - Direct mapping to C ABI │
└────────────────┬────────────────────────────┘
│ (C linkage)
┌────────────────▼────────────────────────────┐
│ C ABI Layer (abi/vdj_plugin_abi.h) │
│ - C-compatible function signatures │
│ - Opaque handles (VdjPlugin, etc) │
│ - Callback structures │
└────────────────┬────────────────────────────┘
│ (C++ implementation)
┌────────────────▼────────────────────────────┐
│ C++ Shim Layer (vdj_plugin_shim/*.cpp) │
│ - Wraps C++ classes from VirtualDJ SDK │
│ - Implements C ABI functions │
│ - Bridges C++ and C/FFI worlds │
└────────────────┬────────────────────────────┘
│ (C++ classes)
┌────────────────▼────────────────────────────┐
│ VirtualDJ C++ SDK Headers (header_ref/) │
│ - IVdjPlugin8 (base plugin interface) │
│ - IVdjPluginDsp8 (audio effects) │
│ - IVdjPluginVideoFx8 (video effects) │
│ - IVdjPluginOnlineSource (online sources) │
└─────────────────────────────────────────────┘
How It Works
- User writes Rust code implementing trait methods (e.g.,
DspPlugin::on_process_samples) - Safe API trait provides default implementations and type safety
- Rust FFI bindings call into C ABI functions (extern "C" declarations)
- C ABI layer defines function signatures that work with C calling conventions
- C++ shim implements those C functions by wrapping the C++ classes from VirtualDJ
- VirtualDJ C++ SDK provides the actual plugin infrastructure
Building
The build script (build.rs) automatically:
- Compiles the C++ shim layer using the
cccrate - Links the compiled C++ code with your Rust code
- Monitors file changes for incremental builds
Creating a Plugin
1. Basic DSP Plugin Template
use ;
2. Available Plugin Types
DspPlugin- Real-time audio effectsBufferDspPlugin- Buffer manipulation (e.g., time-stretching)PositionDspPlugin- Position/playback controlVideoFxPlugin- Video effectsVideoTransitionPlugin- Video transitionsOnlineSourcePlugin- Online music sources/streaming
Key Features
✅ 100% Rust - Write plugins in pure Rust, no C++ needed
✅ Type Safe - Leverages Rust's type system for safety
✅ Error Handling - Rust's Result type for error propagation
✅ ABI Compatible - Fully compatible with VirtualDJ's C++ ABI
✅ Zero Overhead - Direct FFI calls, minimal abstraction cost
✅ Cross-Platform - Works with Windows, macOS implementations
Project Structure
VirtualDJRustSDK/
├── abi/
│ └── vdj_plugin_abi.h # C ABI interface definitions
├── header_ref/
│ ├── vdjPlugin8.h # VirtualDJ base plugin header
│ ├── vdjDsp8.h # DSP plugin header
│ ├── vdjVideo8.h # Video plugin header
│ └── vdjOnlineSource.h # Online source plugin header
├── vdj_plugin_shim/
│ └── basic_plugin_shim.cpp # C++ shim implementation
├── rs_core/
│ ├── lib.rs # Safe Rust API and trait definitions
│ └── ffi.rs # Raw FFI bindings to C ABI
├── examples/
│ └── simple_dsp.rs # Example DSP plugin
├── build.rs # Build script for C++ compilation
├── Cargo.toml # Rust package manifest
└── README.md # This file
Development Workflow
1. Create a new plugin library
2. Add SDK as a dependency
# Cargo.toml
[]
= { = "../VirtualDJRustSDK" }
3. Implement the plugin trait
use DspPlugin;
4. Build your plugin
Error Handling
The SDK provides a PluginError type for error handling:
use ;
FFI Bindings Reference
The low-level FFI bindings are available in rs_core::ffi for advanced use cases:
use *;
// Direct C function calls
unsafe
Note: Direct FFI usage requires unsafe blocks and is not recommended for typical use.
Constants and Flags
Common plugin flags and parameter types are available:
use *;
// Plugin flags
const VDJFLAG_PROCESSFIRST: u32 = 0x4;
const VDJFLAG_PROCESSLAST: u32 = 0x8;
// Parameter types
const VDJPARAM_SLIDER: i32 = 1;
const VDJPARAM_BUTTON: i32 = 0;
Testing
The SDK includes test support for plugin logic:
Run tests with:
Performance Considerations
- Buffer Processing: Buffers are passed as
&mut [f32]slices for zero-copy access - Sample Rates: Typically 44.1kHz or 48kHz (access via
sample_rate()method) - Stereo Format: Audio samples are interleaved (L, R, L, R, ...)
- Real-time: Minimize allocations in
on_process_samples()for best performance
Troubleshooting
Compilation errors with C++
Ensure you have:
- A C++ compiler installed (MSVC on Windows)
- The
cccrate dependency (automatically downloaded)
Symbol resolution errors
The C++ shim must be properly compiled. Check that vdj_plugin_shim/basic_plugin_shim.cpp includes all necessary VirtualDJ headers.
Contributing
Contributions are welcome! Areas for improvement:
- Additional plugin type examples
- Performance optimizations
- Cross-platform testing
- Extended trait methods
License
This project is provided under the MIT or Apache 2.0 license.