Modern, refactored driver for Novation Ultranova and Mininova synthesizers with JACK and PipeWire support.
- ✅ Fixed memory leaks in USB transfer callbacks
- ✅ Fixed race conditions with static variables in callbacks
- ✅ Fixed buffer overflow risks in MIDI message parsing
- ✅ Proper resource cleanup on exit
- ✅ Thread-safe MIDI processing
- ✅ Modern C++17 codebase with RAII patterns
- ✅ Smart pointers for automatic memory management
- ✅ Class-based architecture with clear separation of concerns
- ✅ Improved error handling throughout
- ✅ Better code organization into logical modules
- ✅ PipeWire support - Native support for modern Linux audio
- ✅ Dual backend - Choose between JACK or PipeWire at runtime
- ✅ Better command-line interface with proper argument parsing
- ✅ CMake build system in addition to Makefile
The refactored code is organized into clean, modular components:
src/
├── audio_backend.h/cpp - Abstract audio backend interface
├── jack_backend.h/cpp - JACK implementation
├── pipewire_backend.h/cpp - PipeWire implementation
├── usb_device.h/cpp - USB device management with RAII
├── midi_processor.h/cpp - Thread-safe MIDI message processing
├── automap_controller.h/cpp - Automap protocol and state machine
├── nova_driver.h/cpp - Main driver class
└── main_new.cpp - Application entry point
Required:
- C++17 compatible compiler (GCC 7+, Clang 5+)
- libusb-1.0
- liblo (OSC library)
Optional (at least one required):
- JACK development files (
libjack-devorlibjack-jackd2-dev) - PipeWire development files (
libpipewire-0.3-dev)
# Required packages
sudo apt install build-essential libusb-1.0-0-dev liblo-dev
# JACK support (recommended)
sudo apt install libjack-jackd2-dev
# PipeWire support (optional, for modern systems)
sudo apt install libpipewire-0.3-dev# Required packages
sudo dnf install gcc-c++ libusb-devel liblo-devel
# JACK support
sudo dnf install jack-audio-connection-kit-devel
# PipeWire support
sudo dnf install pipewire-devel# Required packages
sudo pacman -S base-devel libusb liblo
# JACK support
sudo pacman -S jack2
# PipeWire support
sudo pacman -S pipewire# Build debug version (default, with debug symbols)
make
# Build release version (optimized, production-ready)
make release
# Build legacy version (original v1.0 code)
make legacy
# Clean build artifacts
make clean
# Install system-wide
sudo make installBuild Types:
- Debug (
makeormake debug): Includes debug symbols, no optimization, useful for development - Release (
make release): Optimized (-O3), no debug symbols, smaller binary, faster execution - Legacy (
make legacy): Original v1.0 code as fallback
# Create build directory
mkdir build && cd build
# Configure for Release build (default, optimized)
cmake ..
# Or configure for Debug build
cmake -DCMAKE_BUILD_TYPE=Debug ..
# Or explicitly control backends:
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_WITH_JACK=ON -DBUILD_WITH_PIPEWIRE=ON ..
# Build
make -j$(nproc)
# Install (optional)
sudo make installCMake Build Types:
- Release (default):
-O3 -DNDEBUG -march=native - Debug:
-g -O0 -DDEBUG
# Run with JACK (default)
./ultranova4linux
# Run with PipeWire
./ultranova4linux --backend pipewire
# Enable debug output
./ultranova4linux --debug
# Enable Ardour OSC control (Ultranova only)
./ultranova4linux --ardour-osc--backend <type>- Audio backend: 'jack' or 'pipewire' (default: jack)--ardour-osc- Enable Ardour DAW control via OSC--debug- Enable verbose debug output--help- Show help message
Create /etc/udev/rules.d/92-novation.rules:
# Novation Ultranova
SUBSYSTEM=="usb", ATTRS{idVendor}=="1235", ATTRS{idProduct}=="0011", MODE="0664", GROUP="audio"
# Novation Mininova
SUBSYSTEM=="usb", ATTRS{idVendor}=="1235", ATTRS{idProduct}=="001e", MODE="0664", GROUP="audio"Then reload udev rules:
sudo udevadm control --reload-rules
sudo udevadm triggerAdd your user to the audio group:
sudo usermod -a -G audio $USERLog out and back in for group changes to take effect.
Make sure JACK is running before starting the driver:
# Start JACK (example with 48kHz, 256 frames buffer)
jackd -d alsa -r 48000 -p 256PipeWire should be running by default on modern systems. Check status:
systemctl --user status pipewire pipewire-pulse- ✅ Full MIDI I/O
- ✅ Automap control surface support
- ✅ Octave shift controls
- ✅ Rotary encoder support
- ✅ Button mapping
- ✅ LED feedback
- ✅ Ardour DAW integration via OSC
- ✅ MIDI I/O
⚠️ No control surface (hardware limitation)
When using --ardour-osc, the driver provides:
- Encoders 1-8: Control track gain for tracks 1-8
- Encoder 9: Control master bus gain
- Buttons 1-8: Toggle mute for tracks 1-8
- Transport controls: Play, Stop, Loop, Record
- Record enable buttons: Toggle record-enable for tracks 1-8
Make sure Ardour's OSC server is enabled on port 3819.
# Check if device is connected
lsusb | grep Novation
# Check permissions
ls -l /dev/bus/usb/*/# Check if JACK is running
jack_lsp
# Start JACK if needed
jackd -d alsa# Check PipeWire status
pw-cli info
# Check if PipeWire support was compiled in
./ultranova4linux --helpThe new version is backward compatible in terms of functionality. To migrate:
- Build the new version:
make - Test with your existing setup
- The old version can still be built with:
make legacy
Key differences:
- Command-line arguments have changed (use
--help) - Better error messages and logging
- More stable operation
- Support for PipeWire
- AudioBackend: Abstract interface for audio systems
- USBDevice: RAII wrapper for libusb with automatic cleanup
- MidiProcessor: Thread-safe MIDI message parser
- AutomapController: State machine for Automap protocol
- NovaDriver: Main driver coordinating all components
The modular design makes it easy to extend:
- Audio backends: Implement
AudioBackendinterface - MIDI processing: Extend
MidiProcessororAutomapController - USB handling: Use
USBDeviceclass methods
See LICENSE file for details.
Contributions welcome! Please:
- Follow the existing code style
- Add tests for new features
- Update documentation
- Ensure no memory leaks (use valgrind)
- Original driver: ultranova4linux v1.0
- Refactored by: AI Assistant
- PipeWire integration: v2.0
For issues, please provide:
- Linux distribution and version
- Audio backend (JACK/PipeWire version)
- Device model (Ultranova/Mininova)
- Debug output (
--debugflag)