reaper-osc
Version:
Controls Cockos Reaper using OSC
217 lines • 8.3 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeviceSelectedFx = exports.SelectedTrackFxSlot = exports.TrackFx = exports.Fx = void 0;
/**
* Contains classes for controlling FX in Reaper
* @module
*/
const Notify_1 = require("./Notify");
const Commands_1 = require("./Client/Commands");
/**
* A Reaper FX.
*
* @example
* ```typescript
* // Open an FX UI window
* fx.openUi();
* // Bypass the FX
* fx.bypass();
* ```
*/
// @notifyOnPropertyChanged cannot be applied to abstract classes; each concrete subclass applies it.
class Fx {
constructor(name, send) {
this._isBypassed = false;
this._isUiOpen = false;
this._preset = 'No preset';
this._send = send;
this._name = name;
}
/** Indicates whether the FX is bypassed */
get isBypassed() {
return this._isBypassed;
}
/** Indicates whether the FX's UI is open */
get isUiOpen() {
return this._isUiOpen;
}
/** The name of the FX */
get name() {
return this._name;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onPropertyChanged(property, callback) {
throw new Error('not implemented');
}
/**
* The name of the current preset.
*
* **Update behaviour varies by subclass:**
* - `DeviceSelectedFx` — updated in real time whenever the preset changes, because Reaper
* sends `/fx/preset` in response to every preset navigation command.
* - `SelectedTrackFxSlot` and `TrackFx` — only updated during a sync burst
* (`refreshControlSurfaces()`), because Reaper only sends `/fx/{n}/preset` and
* `/track/{n}/fx/{m}/preset` as part of the full state refresh, not in response to
* individual preset commands.
*
* If you need live preset feedback, use `DeviceSelectedFx` (via `selectedTrack.selectedFx`
* after calling `device.selectFx(n)` to point it at the desired slot).
*/
get preset() {
return this._preset;
}
}
__decorate([
Notify_1.notify('isBypassed')
], Fx.prototype, "_isBypassed", void 0);
__decorate([
Notify_1.notify('isUiOpen')
], Fx.prototype, "_isUiOpen", void 0);
__decorate([
Notify_1.notify('name')
], Fx.prototype, "_name", void 0);
__decorate([
Notify_1.notify('preset')
], Fx.prototype, "_preset", void 0);
exports.Fx = Fx;
/**
* An FX on a {@link Track}
*/
let TrackFx = class TrackFx extends Fx {
/**
* @param trackNumber The number of the track the FX is on
* @param fxNumber The FX number in the current bank
* @param send A callback used to send typed commands to Reaper
*/
constructor(trackNumber, fxNumber, send) {
super(`Fx ${fxNumber}`, send);
this.trackNumber = trackNumber;
this.fxNumber = fxNumber;
}
get oscAddress() {
return `/track/${this.trackNumber}/fx/${this.fxNumber}`;
}
handleEvent(event) {
switch (event.type) {
case 'track:fx:name':
if (this._matchesTrackFx(event))
this._name = event.name;
break;
case 'track:fx:bypass':
if (this._matchesTrackFx(event))
this._isBypassed = event.bypassed;
break;
case 'track:fx:openUi':
if (this._matchesTrackFx(event))
this._isUiOpen = event.open;
break;
case 'track:fx:preset':
if (this._matchesTrackFx(event))
this._preset = event.preset;
break;
}
}
_matchesTrackFx(event) {
return event.trackNumber === this.trackNumber && event.fxNumber === this.fxNumber;
}
bypass() { this._send(Commands_1.SetTrackFxBypass(this.trackNumber, this.fxNumber, true)); }
unbypass() { this._send(Commands_1.SetTrackFxBypass(this.trackNumber, this.fxNumber, false)); }
openUi() { this._send(Commands_1.SetTrackFxOpenUi(this.trackNumber, this.fxNumber, true)); }
closeUi() { this._send(Commands_1.SetTrackFxOpenUi(this.trackNumber, this.fxNumber, false)); }
nextPreset() { this._send(Commands_1.NextTrackFxPreset(this.trackNumber, this.fxNumber)); }
previousPreset() { this._send(Commands_1.PreviousTrackFxPreset(this.trackNumber, this.fxNumber)); }
};
TrackFx = __decorate([
Notify_1.notifyOnPropertyChanged
], TrackFx);
exports.TrackFx = TrackFx;
/**
* An FX slot on the OSC device's currently selected track (addressed via `/fx/N/`).
*/
let SelectedTrackFxSlot = class SelectedTrackFxSlot extends Fx {
/**
* @param fxNumber The FX slot number in the device FX bank
* @param send A callback used to send typed commands to Reaper
*/
constructor(fxNumber, send) {
super(`Fx ${fxNumber}`, send);
this.fxNumber = fxNumber;
}
handleEvent(event) {
switch (event.type) {
case 'selectedTrack:fx:name':
if (this._matchesFx(event))
this._name = event.name;
break;
case 'selectedTrack:fx:bypass':
if (this._matchesFx(event))
this._isBypassed = event.bypassed;
break;
case 'selectedTrack:fx:openUi':
if (this._matchesFx(event))
this._isUiOpen = event.open;
break;
case 'selectedTrack:fx:preset':
if (this._matchesFx(event))
this._preset = event.preset;
break;
}
}
_matchesFx(event) {
return event.fxNumber === this.fxNumber;
}
bypass() { this._send(Commands_1.SetSelectedTrackFxBypass(this.fxNumber, true)); }
unbypass() { this._send(Commands_1.SetSelectedTrackFxBypass(this.fxNumber, false)); }
openUi() { this._send(Commands_1.SetSelectedTrackFxOpenUi(this.fxNumber, true)); }
closeUi() { this._send(Commands_1.SetSelectedTrackFxOpenUi(this.fxNumber, false)); }
nextPreset() { this._send(Commands_1.NextSelectedTrackFxPreset(this.fxNumber)); }
previousPreset() { this._send(Commands_1.PreviousSelectedTrackFxPreset(this.fxNumber)); }
};
SelectedTrackFxSlot = __decorate([
Notify_1.notifyOnPropertyChanged
], SelectedTrackFxSlot);
exports.SelectedTrackFxSlot = SelectedTrackFxSlot;
/**
* The OSC device's currently focused FX (addressed via `/fx/` with no slot number).
*/
let DeviceSelectedFx = class DeviceSelectedFx extends Fx {
/**
* @param send A callback used to send typed commands to Reaper
*/
constructor(send) {
super('Selected FX', send);
}
handleEvent(event) {
switch (event.type) {
case 'selectedFx:name':
this._name = event.name;
break;
case 'selectedFx:bypass':
this._isBypassed = event.bypassed;
break;
case 'selectedFx:openUi':
this._isUiOpen = event.open;
break;
case 'selectedFx:preset':
this._preset = event.preset;
break;
}
}
bypass() { this._send(Commands_1.SetSelectedFxBypass(true)); }
unbypass() { this._send(Commands_1.SetSelectedFxBypass(false)); }
openUi() { this._send(Commands_1.SetSelectedFxOpenUi(true)); }
closeUi() { this._send(Commands_1.SetSelectedFxOpenUi(false)); }
nextPreset() { this._send(Commands_1.NextSelectedFxPreset()); }
previousPreset() { this._send(Commands_1.PreviousSelectedFxPreset()); }
};
DeviceSelectedFx = __decorate([
Notify_1.notifyOnPropertyChanged
], DeviceSelectedFx);
exports.DeviceSelectedFx = DeviceSelectedFx;
//# sourceMappingURL=Fx.js.map