Skip to content

About

A reusable JUCE module for license validation across all Cave Acoustics plugins.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

6 Commits

Folders and files

Repository files navigation

CaveLicensing

A reusable JUCE module for license validation across all Cave Acoustics plugins.

Features

  • API-based license validation with Cave Acoustics server
  • Machine ID binding to prevent license sharing
  • Grace period for network outages (7 days default)
  • Automatic periodic revalidation
  • License deactivation support
  • Demo mode with audio interruption
  • Cross-platform support (macOS, Windows, Linux)

Quick Start

1. Add the module to your CMakeLists.txt

# Add the CaveLicensing module
juce_add_module(../../modules/CaveLicensing)

# Link to SharedCode
target_link_libraries(SharedCode
    INTERFACE
    CaveLicensing
    # ... other modules
)

# Define licensing configuration
target_compile_definitions(SharedCode
    INTERFACE
    CAVE_PRODUCT_ID="MYPRODUCT"
    CAVE_PRODUCT_NAME="My Product"
    CAVE_COMPANY_NAME="Cave Acoustics"
    CAVE_API_URL="https://caveacoustics.com/api"
    CAVE_PRODUCT_SLUG="my-product"
)

2. Add members to your processor

// In PluginProcessor.h
#include <CaveLicensing/CaveLicensing.h>

class MyProcessor : public juce::AudioProcessor
{
    // ...
    cave::CaveLicenseManager licenseManager { CAVE_PRODUCT_ID, CAVE_API_URL, CAVE_PRODUCT_SLUG };
    cave::CaveDemoProcessor demoModeProcessor;
};

3. Initialize in constructor

MyProcessor::MyProcessor()
{
    licenseManager.initialize();
}

4. Apply demo mode in processBlock

void MyProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer&)
{
    if (!licenseManager.isLicensed())
    {
        demoModeProcessor.process(buffer);
        if (demoModeProcessor.isInSilencePeriod())
        {
            buffer.clear();
            return;
        }
    }

    // Normal processing...
}

5. Show activation panel in Editor

void MyEditor::showActivationPanel()
{
    if (processorRef.isLicensed())
        return;

    activationPanel = std::make_unique<cave::CaveLicensePanel>(
        processorRef.getLicenseManager(),
        CAVE_PRODUCT_NAME
    );
    activationPanel->onActivationSuccess = [this] {
        updateLicenseButton();
    };
    activationPanel->showAsOverlay(this);
}

Module Classes

CaveLicenseManager

Main license management class with API-based validation.

// Create with product configuration
CaveLicenseManager licenseManager(CAVE_PRODUCT_ID, CAVE_API_URL, CAVE_PRODUCT_SLUG);
licenseManager.initialize();

// Check license status (thread-safe, can call from audio thread)
if (licenseManager.isLicensed()) {
    // Full functionality
}

// Activate with a license key
if (licenseManager.activateLicense("CAVE-XXXX-XXXX-XXXX-XXXX")) {
    // Success
}

// Deactivate (frees up an activation slot)
licenseManager.deactivateLicense();

// Error handling
if (!licenseManager.isLicensed()) {
    auto error = licenseManager.getUserFriendlyError();
    auto hints = licenseManager.getTroubleshootingHints();
}

// Configure revalidation and grace period
licenseManager.setRevalidationIntervalDays(7);  // default
licenseManager.setGracePeriodDays(7);           // default

CaveApiClient

HTTP client for Cave Acoustics license API. Used internally by CaveLicenseManager.

CaveApiClient client(CAVE_API_URL, CAVE_PRODUCT_SLUG);

// Authorize a license
auto response = client.authorize(licenseKey, machineId, machineName);
if (response.success) {
    // response.activationId, response.remainingActivations
}

// Deauthorize
client.deauthorize(licenseKey, machineId);

// Check connectivity
if (client.testConnection()) {
    // Server reachable
}

CaveDemoProcessor

Audio processor that periodically mutes output in demo mode.

  • 3 minutes of normal playback
  • 30 seconds of silence
  • 500ms smooth cosine fades
demoModeProcessor.prepare(sampleRate);
demoModeProcessor.process(buffer);

if (demoModeProcessor.isInSilencePeriod()) {
    // Currently muted
}

CaveLicensePanel

Modal UI component for license activation.

auto panel = std::make_unique<CaveLicensePanel>(licenseManager, "My Product");
panel->onActivationSuccess = [this]() { /* update UI */ };
panel->showAsOverlay(parentComponent);

CaveLicenseConfig

Static configuration for license storage locations.

// Get storage locations
auto dir = CaveLicenseConfig::getLicenseDirectory("MYPRODUCT");
auto file = CaveLicenseConfig::getLicenseFile("MYPRODUCT");

License Key Format

License keys follow the format: CAVE-XXXX-XXXX-XXXX-XXXX

Keys are validated against the Cave Acoustics API server. Upon successful activation, the license is stored locally with an activation timestamp for periodic revalidation.

Network Behavior

Revalidation

Licenses are automatically revalidated with the server every 7 days (configurable). This ensures revoked licenses are detected promptly.

Grace Period

If the server is unreachable during revalidation, a 7-day grace period applies. During this time, previously validated licenses continue to work. After the grace period expires, the plugin reverts to demo mode until connectivity is restored.

Error Handling

The module provides detailed error information:

// Check error type
if (licenseManager.hadNetworkError()) {
    // Connectivity issue - may use grace period
} else {
    // Server rejection (invalid key, revoked, etc.)
}

// Get user-friendly messages
auto error = licenseManager.getUserFriendlyError();
auto hints = licenseManager.getTroubleshootingHints();

File Locations

Licenses are stored in:

  • macOS: ~/Library/Application Support/Cave Acoustics/<ProductID>/license.xml
  • Windows: %APPDATA%/Cave Acoustics/<ProductID>/license.xml
  • Linux: ~/.local/share/Cave Acoustics/<ProductID>/license.xml

Dependencies

  • juce_core
  • juce_cryptography
  • juce_gui_basics
  • juce_audio_basics

License

Proprietary - Cave Acoustics

About

A reusable JUCE module for license validation across all Cave Acoustics plugins.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages