@gorilla-engine-sdk/ge-session-presets-lib
v0.5.13
Published
Session and preset management library for Gorilla Engine React audio plugins.
Readme
@gorilla-engine-sdk/ge-session-presets-lib
Session and preset management for Gorilla Engine React audio plugins.
Provides a React context provider, a default PresetManager implementation,
and the useSessionAndPresets hook that wires together:
- DAW session save / restore via
GorillaEngine.setSessionSaveCallback/setSessionLoadCallback - Preset scanning — recursively scans factory and user preset directories and builds a flat, categorised preset list
- Preset loading, saving, and deletion — with an optional file-system watcher that keeps the list up to date
- Hook-in callbacks — inject custom logic at any lifecycle point (pre/post-load, save, delete) without subclassing
Install
npm install @gorilla-engine-sdk/ge-session-presets-libPeer Dependencies: Requires @gorilla-engine-sdk/gorilla-engine-react ^1.x
and @gorilla-engine-sdk/ge-dialogs-lib ^0.x
Quick Start
The typical setup uses @gorilla-engine-sdk/ge-blob-manager to load the
instrument blob, then passes the resulting instrument to SessionAndPresetsStateProvider.
import path from 'path';
import { useState } from 'react';
import { BlobManager } from '@gorilla-engine-sdk/ge-blob-manager';
import { LabeledKnob, LabeledSlider } from '@gorilla-engine-sdk/ge-labeled-components';
import {
SessionAndPresetsConfig,
SessionAndPresetsStateProvider,
SessionAndPresetsWrapper,
useSessionAndPresets,
defaultSessionAndPresetsConfig,
} from '@gorilla-engine-sdk/ge-session-presets-lib';
const config: SessionAndPresetsConfig = {
...defaultSessionAndPresetsConfig,
factoryPresetPath: path.join(GorillaEngine.getResourcePath(), 'Presets'),
userPresetPath: path.join(GorillaEngine.getUserDataPath(), 'Presets'),
flagPresetChanged: true, // mark "*" when parameters deviate from preset
roundtripPresets: true, // wrap around at the end of the preset list
};
// --- Root: rendered by Gorilla Engine ---
export function Root() {
const [instrument, setInstrument] = useState<GorillaEngine.Instrument | null>(null);
// While the blob hasn't loaded yet, show BlobManager which handles
// discovery, optional native file-chooser dialog, and instrument init.
if (!instrument) {
return (
<geLabel width={800} height={600}>
<BlobManager
pluginName="MyPlugin"
manufacturerName="MyCompany"
blobName="MyPlugin"
onInstrumentLoaded={(inst) => setInstrument(inst)}
onErrorLoadingInstrument={(err) => console.error('Blob load error:', err)}
/>
</geLabel>
);
}
return (
<SessionAndPresetsStateProvider config={config} instrument={instrument}>
<SessionAndPresetsWrapper>
<App />
</SessionAndPresetsWrapper>
</SessionAndPresetsStateProvider>
);
}
// --- Plugin UI: has access to all session/preset context hooks ---
function App() {
const { prevPreset, nextPreset, getLoadedPreset } = useSessionAndPresets();
const presetName = getLoadedPreset()?.name ?? '—';
return (
<geLabel width={800} height={600}>
{/* Preset navigation toolbar */}
<geLabel x={10} y={10} width={400} height={40}>
<geButton x={0} width={40} height={40} text="◀" onClick={prevPreset} />
<geLabel x={45} width={310} height={40} text={presetName} />
<geButton x={360} width={40} height={40} text="▶" onClick={nextPreset} />
</geLabel>
{/* Main controls — ge-labeled-components handles label + value display */}
<LabeledKnob
x={60}
y={100}
width={80}
height={100}
parameterPath="/macro/cutoff"
label="Cutoff"
/>
<LabeledKnob
x={180}
y={100}
width={80}
height={100}
parameterPath="/macro/resonance"
label="Reso"
/>
<LabeledSlider
x={320}
y={80}
width={40}
height={120}
parameterPath="/macro/volume"
label="Volume"
/>
</geLabel>
);
}Configuration
SessionAndPresetsConfig
| Field | Type | Default | Description |
| ------------------------ | ---------- | --------------- | --------------------------------------------------------------------------- |
| presetFileSuffix | string | '.patch' | File extension used to identify preset files |
| factoryPresetType | string | 'FACTORY' | Type tag applied to factory presets |
| factoryPresetPath | string? | — | Absolute path to the factory preset directory |
| userPresetType | string | 'USER' | Type tag applied to user presets |
| userPresetPath | string? | — | Absolute path to the user preset directory |
| handleSession | boolean | true | Register DAW session save/load callbacks |
| handlePresets | boolean | true | Enable preset scanning and management |
| autoLoadPresets | boolean | true | Scan preset directories automatically on startup |
| loadInitialPreset | boolean | true | Load the first (or initialPresetPath) preset on startup |
| handleErrors | boolean | true | Show built-in error dialogs on failure |
| retainUIScale | boolean | true | Persist and restore UI scale with session data |
| roundtripPresets | boolean? | false | Wrap around when navigating past the last/first preset |
| flagPresetChanged | boolean? | false | Track unsaved preset changes |
| stripCategoryPrefix | boolean? | — | Remove a prefix used for sort ordering from category names |
| categoryPrefix | string? | — | The prefix to strip (e.g. '00^^') |
| pluginType | string? | auto-detected | Plugin format ('VST', 'AAX', etc.) |
| blockAAXInitialSession | boolean | false | Skip the first session restore on AAX (handles Pro Tools startup behaviour) |
| debug | boolean? | false | Enable verbose console output |
defaultSessionAndPresetsConfig
A ready-to-use baseline configuration:
const defaultSessionAndPresetsConfig: SessionAndPresetsConfig = {
presetFileSuffix: '.patch',
factoryPresetType: 'FACTORY',
userPresetType: 'USER',
handleSession: true,
handlePresets: true,
autoLoadPresets: true,
loadInitialPreset: true,
handleErrors: true,
flagPresetChanged: false,
retainUIScale: true,
blockAAXInitialSession: false,
debug: false,
};API Reference
SessionAndPresetsStateProvider
Top-level context provider. Wrap your plugin root with this component.
Props:
| Prop | Type | Description |
| --------------- | -------------------------- | --------------------------------- |
| config | SessionAndPresetsConfig | Session and preset configuration |
| instrument | GorillaEngine.Instrument | Current instrument instance |
| presetManager | IPresetManager? | Custom preset manager (optional) |
| state | SessionAndPresetsState? | Initial state override (optional) |
SessionAndPresetsWrapper
Orchestrator component. Place it inside SessionAndPresetsStateProvider. It:
- Registers DAW session save/load callbacks
- Triggers initial preset scanning
- Watches the user preset directory for changes
- Loads the initial preset once scanning completes
useSessionAndPresets()
Primary hook for preset and session operations. Returns the following functions:
| Function | Description |
| ------------------------------- | ---------------------------------------------------------------------------- |
| saveSession(stateString) | Called by the DAW session save callback; serialises instrument state |
| loadSession(stateJSON) | Called by the DAW session load callback; restores instrument state |
| loadPresets(dirs) | Scans an array of directory descriptors and populates the preset list |
| getPreset(uuid) | Returns the Preset object with the given UUID |
| getLoadedPreset() | Returns the currently loaded Preset object |
| loadPreset(obj) | Loads a preset from an in-memory object |
| loadPresetFromSource(path) | Loads a preset from a file path |
| createPreset() | Creates and returns an in-memory preset object from current instrument state |
| savePreset(path) | Saves the current instrument state to a preset file |
| saveAsPreset() | Opens a native save dialog and saves to the chosen path |
| deletePreset(path) | Deletes a preset file and loads the first available preset |
| resetInstrumentProperty(name) | Resets a single instrument property to its preset value |
| prevPreset() | Loads the previous preset in the list |
| nextPreset() | Loads the next preset in the list |
| randomize() | Loads a random preset |
| randomizeInCategory() | Loads a random preset in the current category |
PresetManager
Default implementation of IPresetManager. Extend this class to add custom
behaviour at any lifecycle point without touching the library internals.
A common use case is embedding plugin-version metadata in preset files and migrating older presets on load:
import { PresetManager, SessionAndPresetsConfig } from '@gorilla-engine-sdk/ge-session-presets-lib';
const MY_VERSION = '1.2.0';
class MyPresetManager extends PresetManager {
constructor(config: SessionAndPresetsConfig) {
super(config);
// Stamp the current plugin version into every preset on save
this.setAdditionalSavePreset(async (_instrument, presetObj) => {
presetObj.additionalData = {
...presetObj.additionalData,
pluginVersion: MY_VERSION,
};
});
// Migrate presets saved by older plugin versions on load
this.setAdditionalLoadPreset(async (instrument, presetObj) => {
const savedVersion = presetObj.additionalData?.pluginVersion ?? '0.0.0';
if (savedVersion < '1.0.0') {
// e.g. remap a renamed parameter path
const oldValue = instrument.getDoubleAtPath('/legacy/brightness');
instrument.setDoubleAtPath('/macro/cutoff', oldValue);
}
});
}
}Pass the custom manager to the provider:
<SessionAndPresetsStateProvider
config={config}
instrument={instrument}
presetManager={new MyPresetManager(config)}
>
<SessionAndPresetsWrapper>
<App />
</SessionAndPresetsWrapper>
</SessionAndPresetsStateProvider>Hook-in callbacks
PresetManager exposes pairs of setAdditional* / removeAdditional*
methods for each lifecycle point:
| Method pair | When called |
| -------------------------------------------------- | ------------------------------------------------ |
| setAdditionalSaveSession / remove… | After session object is created |
| setAdditionalPreLoadSession / remove… | Before session data is applied |
| setAdditionalLoadSession / remove… | After session restore is complete |
| setAdditionalCreatePresetItem / remove… | When a preset file is discovered during scanning |
| setAdditionalPreLoadPreset / remove… | Before preset data is applied to instrument |
| setAdditionalLoadPreset / remove… | After preset data is applied to instrument |
| setAdditionalPreLoadPresetFromSource / remove… | Before preset file is read from disk |
| setAdditionalLoadPresetFromSource / remove… | After preset file is applied |
| setAdditionalCreatePreset / remove… | When a preset object is created in memory |
| setAdditionalPreSavePreset / remove… | Before preset is written to disk |
| setAdditionalSavePreset / remove… | After preset is written to disk |
| setAdditionalDeletePreset / remove… | After a preset file is deleted |
SessionAndPresetsError
All errors thrown by the library are instances of SessionAndPresetsError,
which carries:
type— one ofSessionAndPresetsErrorTypesfor programmatic handlingdefaultTitle— short display titledefaultMessage— human-readable descriptiondetails— optional debugging context
When config.handleErrors is true, the library automatically shows an error
dialog using ge-dialogs-lib. Set it to false to handle errors yourself:
try {
await loadPresetFromSource(filePath);
} catch (err) {
if (err instanceof SessionAndPresetsError) {
myErrorReporter.report(err.type, err.defaultMessage);
}
}