http://moddevices.com/ns/ext/license — version v1.3.2
The MOD License extension defines a lightweight protocol for LV2 plugin copy-protection and trial mode. It describes how a host communicates license file contents to a plugin, and how the plugin reports its licensed status back to the host.
This extension is designed so that the host carries no cryptographic logic. The host only knows where license files are stored and how to pass their contents to the plugin. All verification is performed inside the plugin binary using libmodla, the reference implementation library distributed by MOD Audio to plugin developers.
| URI | Role | Used by |
|---|---|---|
http://moddevices.com/ns/ext/license#feature |
LV2 feature the host provides to the plugin at instantiate time. Carries the license file retrieval function. | Host → Plugin |
http://moddevices.com/ns/ext/license#interface |
LV2 extension data interface the plugin exposes. Allows the host to query license status and licensee name. | Plugin → Host |
A license file is a plain text file. Its filename is the SHA-1 hash of the plugin URI it applies to. The file contains six lines:
John Doe http://example.com/my-plugin 0F1E2D3C48796A5B4C3D2E1F0B5A6978 obiYTZ0hW/eEkUi4ZZCDaxWiezrATf+yeH4dPMT+Eul2ypPGYqFqstbNjA2UBuJx jwEH705c07jvyF/d3Id+0DPCk012nDUd0WxqNXrKH7ZXycyu0IXWxxONp7DDpj1z ht2vvZgk42DW3k5U942SUN4TRjdPEK5HY/sBOslqBO0=
Lines 1–3 are the plaintext payload: licensee name, plugin URI, and device hardware unique ID. Lines 4–6 are the RSA/SHA-1 signature of lines 1–3, base64-encoded, signed with MOD Audio's private key.
If any of the first three lines are altered, the signature will no longer match and the plugin will run in trial mode. The private key never leaves MOD Audio's infrastructure.
A host that supports this extension must provide the MOD_LICENSE__feature LV2
feature to plugins at instantiate time. This feature carries a
MOD_License_Feature struct with two function pointers:
typedef struct _MOD_License_Feature {
MOD_License_Handle handle;
/* Returns the contents of the license file for license_uri,
or NULL if no license exists. Caller must free() the result. */
char* (*license)(MOD_License_Handle handle, const char* license_uri);
/* Frees the data returned by license(). */
void (*free)(MOD_License_Handle handle, char* license);
} MOD_License_Feature;
The host is responsible for knowing where license files are stored on the device (by default
/root/keys/, configurable via the MOD_KEYS_PATH environment
variable). The host reads the file and returns its raw contents. It performs no validation.
The host may also query a loaded plugin instance for its license status by calling
extension_data(MOD_LICENSE__interface), which returns a
MOD_License_Interface struct:
typedef struct _MOD_License_Interface {
/* Returns MOD_License_Status for the plugin instance. */
int (*status)(LV2_Handle instance);
/* Returns the licensee name, or NULL if unlicensed.
Caller must free() the result. */
char* (*licensee)(LV2_Handle instance);
} MOD_License_Interface;
| Constant | Value | Meaning |
|---|---|---|
MOD_LICENSE_SUCCESS |
0 | Plugin is licensed and running normally. |
MOD_LICENSE_ERR_UNKNOWN |
1 | License check failed for an unspecified reason. |
MOD_LICENSE_ERR_UNLICENSED |
2 | No valid license found. Plugin runs in trial mode: audio passes through for ~37.5s, then silences for ~6.2s, repeating in a ~43.7s cycle for as long as the plugin remains unlicensed — not a one-time cutoff. |
MOD_LICENSE_ERR_UNSUPPORTED |
3 | Reported by a plugin instance that does not implement this API at all — not a status a protected plugin reports on itself. A host that doesn't provide MOD_LICENSE__feature does not exempt a protected plugin from restriction: the check simply fails, and the plugin runs the same trial/silence behaviour as when no valid license is found. |
When no valid license is found, the plugin runs in trial mode. This is not a one-time cutoff: internally, libmodla counts elapsed audio samples in a counter that wraps every 221 samples, and injects silence into all output buffers only once that counter has passed 1,800,000. At the 48kHz sample rate used across MOD hardware, that means audio passes through normally for approximately 37.5 seconds, then silences for approximately 6.2 seconds as the counter finishes its cycle, then resumes passing audio for another ~37.5 seconds — repeating in a ~43.7-second cycle for as long as the plugin remains unlicensed. This behaviour is implemented inside the plugin binary via libmodla and requires no action from the host.
Trial mode is the default state for any plugin that links libmodla and has not yet been purchased. Every plugin on a MOD-powered marketplace is freely triable without account creation or time limits on the trial period itself.
A plugin that supports this extension must declare it in its LV2 .ttl metadata:
<http://example.com/your-plugin>
a lv2:Plugin ;
lv2:extensionData <http://moddevices.com/ns/ext/license#interface> ;
lv2:requiredFeature <http://moddevices.com/ns/ext/license#feature> .
Plugin developers receive a redistribution package from MOD Audio (via their hardware
partner) containing the pre-compiled libmodla.a static library, this header, and
an example plugin. Integration requires four steps:
/* 1. Include the header */ #include <libmodla.h> /* 2. Add run_count to your plugin struct, initialized to 0 */ uint32_t run_count; /* 3. Call at instantiate() — once per license URI */ mod_license_check(features, "http://example.com/your-plugin"); /* 4. Call at the start of run() */ run_count = mod_license_run_begin(run_count, n_samples); /* 5. Call at the end of run() for each audio output buffer */ mod_license_run_silence(run_count, audio_out[i], n_samples, i); /* 6. Return from extension_data() */ return mod_license_interface(uri);
See the example plugin included in the redistribution package for a complete working implementation. For access to the redistribution package, contact your hardware platform provider or sales@mod.audio.