Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DRIFT

DRIFT shreds incoming audio into a cloud of 1,024 grains, then suspends them in a tunable field of pitch, time and space. The result sits somewhere between reverb, delay and synthesis — perfect for ambient pads, dimensional vocals, or pulling a kick drum into a 14‑second tail without losing its punch. Modulation runs internally so motion is built in, not bolted on.

A sample / reference JUCE 8 audio plugin for Corino. Like corino-halo, DRIFT is a polished, decorative demo — the knobs are real, automatable parameters but do not process audio. Its job is to showcase Moonbase licensing in a real VST3 / AU / Standalone plugin.

Where HALO integrates the older juce::OnlineUnlockStatus bridge, DRIFT uses the newer moonbase_licensing JUCE module: native Moonbase API integration (no OnlineUnlockStatus), a brandable built‑in activation UI, and zero third‑party dependencies (JUCE WebInputStream transport, vendored nlohmann/json, OS‑native RS256 crypto).

DRIFT activation screen

The build produces standard plugin bundles plus a standalone app — no installer:

Format Output
VST3 build/DRIFT_artefacts/<config>/VST3/DRIFT.vst3 (macOS / Windows / Linux)
Audio Unit build/DRIFT_artefacts/<config>/AU/DRIFT.component (macOS only)
Standalone build/DRIFT_artefacts/<config>/Standalone/DRIFT.{app,exe} (macOS / Windows / Linux)

What it demonstrates

  • The moonbase_licensing module wired into a plugin via CMake + juce_add_module.
  • A single branded ActivationConfig (src/Licensing.h) driving both the audio‑thread license gate and the activation overlay.
  • The processor as the licensing source of truth (a headless ActivationController
    • a std::atomic<bool> read on the audio thread), so gating works with the editor closed.
  • The module's brandable ActivationComponent shown as a modal overlay from a Manage License button — no hand‑built activation screens.
  • Audio gated by license: the output is silent until the plugin is activated.
  • A HALO‑grade native GUI: bundled fonts, a custom LookAndFeel, custom knobs, and the signature animated grain‑field visual driven live by the (decorative) parameters.

What the licensing actually requires

DRIFT is mostly decoration wrapped around a small licensing core. If you are using this as a reference, the complete strictly‑required surface is below — everything else (the knobs, the grain field, fonts, LookAndFeel, the processor's atomic gate plumbing) is DRIFT‑specific polish you can drop. In the source, the required bits are marked with // [moonbase] REQUIRED and the rest with // [drift] decoration.

Build wiring — the only licensing‑specific lines in CMakeLists.txt:

include(FetchContent)
FetchContent_Declare(moonbase_cpp
    GIT_REPOSITORY https://github.com/Moonbase-sh/moonbase-cpp.git
    GIT_TAG        <pinned commit or release tag>
    SOURCE_SUBDIR  modules)        # populate only — don't add moonbase-cpp's root CMake
FetchContent_MakeAvailable(moonbase_cpp)
juce_add_module(${moonbase_cpp_SOURCE_DIR}/modules/moonbase_licensing)

target_link_libraries(DRIFT PRIVATE moonbase_licensing)
target_compile_definitions(DRIFT PRIVATE JUCE_USE_CURL=0)   # use the module's zero-dep transport
if(APPLE)
    enable_language(OBJC OBJCXX)   # the module has a Security.framework Obj-C++ unit
endif()

No brew / vcpkg / apt packages, no OpenSSL/curl. JUCE 8 only.

Configure — three required fields (src/Licensing.h); everything else on ActivationConfig is optional branding:

ActivationConfig config;
config.endpoint  = "https://your-tenant.moonbase.sh";  // REQUIRED
config.productId = "your-product";                      // REQUIRED
config.publicKey = yourTenantPublicKeyPem;              // REQUIRED

Own the controller in the processor, share it with the editor — one license, and gating that's correct whether or not the editor is open:

// AudioProcessor member:
moonbase::juce_integration::ActivationController license { config };
license.start();                                  // load + validate any stored license

// In createEditor(): the overlay shares the processor's controller (non-owning).
auto* editor = new ActivationComponent (processor.license);
// onClose -> dismiss(); resized() -> setBounds(); Manage button -> appear();

Gate the audio off the controller's lock-free flag — no ChangeListener:

if (! license.licensedFlag().load())
    buffer.clear();                               // silent until activated

…or use LicenseGate for a click-free fade on activate/deactivate (what DRIFT does):

moonbase::juce_integration::LicenseGate gate;     // AudioProcessor member
void prepareToPlay (double sr, int) override { gate.prepare (sr); gate.reset (license.licensedFlag().load()); }
void processBlock (juce::AudioBuffer<float>& b, ...) override
{
    gate.process (b.getArrayOfWritePointers(), b.getNumChannels(), b.getNumSamples(),
                  license.licensedFlag().load());
}

applicationVersion is auto-filled from JucePlugin_VersionString in a plugin, so telemetry reports the build version with no wiring. Everything else — DriftLookAndFeel, DriftKnob, GrainField, MiniMeter, Branding.h, the bundled fonts/logo — is pure DRIFT styling, unrelated to licensing.

Build

Requires CMake ≥ 3.22 and a C++17 toolchain. JUCE 8.0.4 and the moonbase_licensing module are both fetched automatically on the first configure (via CMake FetchContent), so there are no git submodules — a plain clone is the whole setup.

git clone <this-repo>
cd <this-repo>

cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build

Artefacts land in build/DRIFT_artefacts/<config>/{VST3,AU,Standalone}/. There is nothing to brew / vcpkg / apt install — the module uses OS‑native crypto (Security.framework / CNG / system libcrypto). On Linux only, install libssl-dev for libcrypto plus the usual JUCE X11/ALSA/FreeType packages (see .github/workflows/ci.yml).

Run the standalone

scripts/run.sh            # configure + build + launch DRIFT.app (macOS)
scripts/run.sh --clean    # wipe build/ first

Install for DAW testing

run.sh only builds the Standalone. To test in a DAW, build + install the plugin formats (COPY_PLUGIN_AFTER_BUILD copies them into your plugin folders):

scripts/install.sh             # build + install VST3 (+ AU on macOS)
scripts/install.sh --validate  # ...then run auval on the AU (macOS)

Installs to ~/Library/Audio/Plug-Ins/VST3/DRIFT.vst3 and ~/Library/Audio/Plug-Ins/Components/DRIFT.component (macOS), or ~/.vst3 (Linux).

Both scripts auto-pin the macOS SDK to the active Xcode (so JUCE's juceaide compiles even when newer Command Line Tools SDKs are installed); a raw cmake invocation may need DEVELOPER_DIR / SDKROOT set manually.

End-to-end test

  1. Launch the standalone (scripts/run.sh). With no stored license the activation overlay appears and the plugin is locked — audio output is silent.
  2. Click Activate online → your browser opens the Moonbase activation page for the Corino demo tenant.
  3. Sign in / fulfil the activation in the browser.
  4. Within ~1 second the overlay dismisses and audio un‑mutes (a click‑free LicenseGate fade).
  5. Quit and relaunch — activation is skipped: the stored license at ~/Library/Application Support/Corino/DRIFT/license.mb (platform‑appropriate path) is validated on startup.
  6. Re‑open the overlay from the Manage License button to inspect license details, or Deactivate to release the seat on the server and re‑lock the plugin.

In a DAW, install the plugin (scripts/install.sh) and do the same from the VST3 / AU — gating is driven by the processor, so it behaves identically with the editor closed.

Licensing configuration

Everything lives in src/Licensing.h. It targets the Corino demo tenant (corino-demo.moonbase.sh, product drift). The RSA public key is per‑tenant (it signs every product's tokens), so it's the same key HALO embeds.

To ship against your own tenant or product, swap endpoint / productId / publicKey for the values from your Moonbase dashboard. A wrong key/product does not break the build — activation simply routes to the Welcome/Error screen until corrected. The validated license is cached at ~/Library/Application Support/Corino/DRIFT/license.mb (platform‑appropriate path), so relaunching skips activation.

The module dependency

moonbase-cpp is pulled via CMake FetchContent (the same mechanism as JUCE) and pinned to a specific commit on the module's upstream main branch (PR #14 is merged). Only the modules/moonbase_licensing folder is consumed — SOURCE_SUBDIR modules stops FetchContent from adding moonbase-cpp's root CMake (and the SDK's OpenSSL/CURL target).

To move to a newer commit (or a release tag once the module ships in one), bump GIT_TAG in CMakeLists.txt and re‑configure:

# edit GIT_TAG in CMakeLists.txt, then:
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release   # re-fetches at the new pin

To hack on the module against a local checkout without touching the pin, point FetchContent at it:

cmake -B build -DFETCHCONTENT_SOURCE_DIR_MOONBASE_CPP=/path/to/moonbase-cpp ...

CI

ci.yml runs on every push/PR and builds on macOS (VST3/AU/Standalone), Windows (VST3/Standalone) and Linux (VST3/Standalone), uploading the built bundles as workflow artifacts. Both JUCE and the licensing module are fetched during configure, so checkout needs no submodule step and no token (moonbase-cpp is public).

Releasing

release.yml builds the plugin bundles and publishes them straight to the Moonbase tenant (corino-demo.moonbase.sh, product drift) as a new release, following the GitHub Actions product‑release recipe. It ships macOS (arm64) and Windows (x64) and attaches both; Linux is built in CI but not published (add another build-* job + downloads entry to change that).

One-time setup

  1. In the Moonbase tenant dashboard, create a Merchant API key with permission to manage product downloads.
  2. In this repo → Settings → Secrets and variables → Actions, add a secret named MOONBASE_API_KEY containing that key.
  3. Confirm MOONBASE_TENANT_HOST / MOONBASE_PRODUCT_ID at the top of release.yml match the config in src/Licensing.h (default: corino-demo.moonbase.sh / drift).

Cutting a release

git tag v1.0.1
git push origin v1.0.1

The workflow resolves the version from the tag, builds and zips the bundles per platform (ditto --keepParent on macOS so the bundle structure + xattrs survive), uploads each via POST /api/downloads/preparePUT, then publishes a single release with both downloads via POST /api/products/drift/releases/new. You can also run it manually from the Actions tab — supply the version (1.2.3) and choose whether to publish immediately or leave the release as a draft for review in the dashboard.

Source layout

CMakeLists.txt            # FetchContent JUCE + moonbase_licensing module, juce_add_plugin
resources/fonts/          # Space Grotesk, Inter, JetBrains Mono
resources/logo/drift.svg
scripts/run.sh            # configure + build + launch Standalone (macOS)
scripts/install.sh        # build + install VST3 (+ AU on macOS), --validate runs auval
src/
  PluginProcessor.{h,cpp} # licensing source of truth: ActivationController + atomic gate + LicenseGate
  PluginEditor.{h,cpp}    # plugin UI + ActivationComponent overlay (Manage License)
  Licensing.h             # [moonbase] REQUIRED ActivationConfig (endpoint / productId / publicKey)
  Branding.h              # palette + font names + background painter
  DriftLookAndFeel.{h,cpp}# bundled-font wiring + custom controls
  ParamIDs.h              # decorative parameter IDs
  ui/
    DriftKnob.{h,cpp}     # custom rotary knob
    GrainField.{h,cpp}    # animated grain-field visual
    MiniMeter.{h,cpp}     # footer IN/OUT meter

Design

DRIFT's visual identity is the cool counterpart to HALO's warm amber: an aqua/teal accent suspended in a deep blue‑black field — the "cloud of grains" between reverb, delay and synthesis. It's defined in src/Branding.h:

  • Background — charcoal‑blue vertical gradient (#0e1318#070a0d) with teal and indigo radial washes.
  • Accent — aqua/teal #5fd4cf (bright #9ff0ea, deep #2c8f8a).
  • Foreground — cool off‑white #eef4f5.
  • Type — Space Grotesk (display), JetBrains Mono (technical labels), Inter (body).

The signature element is the animated grain field (src/ui/GrainField.*), driven live by the decorative parameters.

License

This sample is MIT‑licensed (see LICENSE). JUCE 8 is licensed separately — this project consumes JUCE under the GPLv3 path implicit in FetchContent; see JUCE's licensing terms. The Moonbase module is MIT‑licensed. Bundled fonts ship under their respective SIL Open Font Licenses.

About

Reference implementation for moonbase-cpp licensing in a JUCE app

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages