reaper-osc
Version:
Controls Cockos Reaper using OSC
400 lines • 14.7 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.Track = exports.RecordMonitoringMode = void 0;
/** Contains classes for controlling tracks in Reaper
* @module
*/
const Fx_1 = require("./Fx");
const Send_1 = require("./Send");
const Receive_1 = require("./Receive");
const Notify_1 = require("./Notify");
const Events_1 = require("./Client/Events");
const Commands_1 = require("./Client/Commands");
var Events_2 = require("./Client/Events");
Object.defineProperty(exports, "RecordMonitoringMode", { enumerable: true, get: function () { return Events_2.RecordMonitoringMode; } });
/** A Reaper track */
let Track = class Track {
/**
* @param trackNumber The track's number in the current bank
* @param numberOfFx The number of FX per FX bank
* @param numberOfSends The number of sends per track
* @param numberOfReceives The number of receives per track
* @param send A callback used to send typed commands to Reaper
*/
constructor(trackNumber, numberOfFx, numberOfSends, numberOfReceives, send) {
this.trackNumber = trackNumber;
this._isMuted = false;
this._isRecordArmed = false;
this._isSelected = false;
this._isSoloed = false;
this._name = 'Track' + this.trackNumber;
this._pan = 0;
this._pan2 = 0;
// TODO: Find out what the modes are - should this be an enum value?
this._panMode = '';
this._recordMonitoring = Events_1.RecordMonitoringMode.OFF;
this._volumeDb = 0;
this._volumeFaderPosition = 0;
this._vu = 0;
this._vuLeft = 0;
this._vuRight = 0;
this._fx = [];
this._sends = [];
this._receives = [];
this._send = send;
for (let i = 0; i < numberOfFx; i++) {
this._fx[i] = new Fx_1.TrackFx(trackNumber, i + 1, send);
}
for (let i = 0; i < numberOfSends; i++) {
this._sends[i] = new Send_1.TrackSend(trackNumber, i + 1, send);
}
for (let i = 0; i < numberOfReceives; i++) {
this._receives[i] = new Receive_1.TrackReceive(trackNumber, i + 1, send);
}
}
/**
* Deselect the track in the Reaper project.
* Note: this affects Reaper's project-level track selection (visible in the UI).
* To change which track the OSC device is focused on, use {@link DeviceState.selectTrack} instead.
*/
deselect() {
this._send(Commands_1.SetTrackSelect(this.trackNumber, false));
}
/** The track's current FX bank */
get fx() {
return this._fx;
}
/** The track's sends */
get sends() {
return this._sends;
}
/** The track's receives */
get receives() {
return this._receives;
}
/**
* Handle a typed incoming event
* @param event The event to handle
*/
handleEvent(event) {
switch (event.type) {
case 'track:name':
if (event.trackNumber === this.trackNumber)
this._name = event.name;
break;
case 'track:mute':
if (event.trackNumber === this.trackNumber)
this._isMuted = event.muted;
break;
case 'track:solo':
if (event.trackNumber === this.trackNumber)
this._isSoloed = event.soloed;
break;
case 'track:recordArm':
if (event.trackNumber === this.trackNumber)
this._isRecordArmed = event.armed;
break;
case 'track:monitoringMode':
if (event.trackNumber === this.trackNumber)
this._recordMonitoring = event.mode;
break;
case 'track:select':
if (event.trackNumber === this.trackNumber)
this._isSelected = event.selected;
break;
case 'track:pan':
if (event.trackNumber === this.trackNumber)
this._pan = event.pan;
break;
case 'track:pan2':
if (event.trackNumber === this.trackNumber)
this._pan2 = event.pan2;
break;
case 'track:panMode':
if (event.trackNumber === this.trackNumber)
this._panMode = event.panMode;
break;
case 'track:volume':
if (event.trackNumber === this.trackNumber)
this._volumeFaderPosition = event.volume;
break;
case 'track:volumeDb':
if (event.trackNumber === this.trackNumber)
this._volumeDb = event.volumeDb;
break;
case 'track:vu':
if (event.trackNumber === this.trackNumber)
this._vu = event.vu;
break;
case 'track:vuLeft':
if (event.trackNumber === this.trackNumber)
this._vuLeft = event.vuLeft;
break;
case 'track:vuRight':
if (event.trackNumber === this.trackNumber)
this._vuRight = event.vuRight;
break;
case 'track:fx:name':
case 'track:fx:bypass':
case 'track:fx:openUi':
case 'track:fx:preset':
if (event.trackNumber === this.trackNumber) {
const fx = this._fx[event.fxNumber - 1];
if (fx)
fx.handleEvent(event);
}
break;
case 'track:send:name':
case 'track:send:volume':
case 'track:send:volumeStr':
case 'track:send:pan':
case 'track:send:panStr':
if (event.trackNumber === this.trackNumber) {
const send = this._sends[event.sendNumber - 1];
if (send)
send.handleEvent(event);
}
break;
case 'track:recv:name':
case 'track:recv:volume':
case 'track:recv:volumeStr':
case 'track:recv:pan':
case 'track:recv:panStr':
if (event.trackNumber === this.trackNumber) {
const receive = this._receives[event.receiveNumber - 1];
if (receive)
receive.handleEvent(event);
}
break;
}
}
/** Indicates whether the track is muted */
get isMuted() {
return this._isMuted;
}
/** Indicates whether the track is armed for recording */
get isRecordArmed() {
return this._isRecordArmed;
}
/**
* Indicates whether the track is selected in the Reaper project.
* Note: this reflects Reaper's project-level selection, not the OSC device's focused track.
* @see {@link DeviceState.selectTrack} and {@link Reaper.selectedTrack}
*/
get isSelected() {
return this._isSelected;
}
/** Indicates whether the track is soloed */
get isSoloed() {
return this._isSoloed;
}
/** Mute the track */
mute() {
this._send(Commands_1.SetTrackMute(this.trackNumber, true));
}
/** The track name */
get name() {
return this._name;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onPropertyChanged(property, callback) {
throw new Error('not implemented');
}
/** A floating-point value between -1 and 1 that indicates the pan position, with -1 being 100% left and 1 being 100% right */
get pan() {
return this._pan;
}
/** A floating-point value between -1 and 1 that indicates the pan 2 position, with -1 being 100% left and 1 being 100% right */
get pan2() {
return this._pan2;
}
/** The current pan mode */
get panMode() {
return this._panMode;
}
/** Arm the track for recording */
recordArm() {
this._send(Commands_1.SetTrackRecordArm(this.trackNumber, true));
}
/** Indicates the record monitoring mode */
get recordMonitoring() {
return this._recordMonitoring;
}
/** Disarm track recording */
recordDisarm() {
this._send(Commands_1.SetTrackRecordArm(this.trackNumber, false));
}
/**
* Renames the track
* @param name The new name of the track
* @example
* ```typescript
* // Change the track name to 'Guitar'
* track.rename('Guitar');
* ```
*/
rename(name) {
this._send(Commands_1.SetTrackName(this.trackNumber, name));
// Reaper will not send a name message in response
this._name = name;
}
/**
* Select the track in the Reaper project.
* Note: this affects Reaper's project-level track selection (visible in the UI).
* To change which track the OSC device is focused on, use {@link DeviceState.selectTrack} instead.
*/
select() {
this._send(Commands_1.SetTrackSelect(this.trackNumber, true));
}
/**
* Set the record monitoring mode
* @param {RecordMonitorMode} value
* */
setMonitoringMode(value) {
this._send(Commands_1.SetTrackMonitoringMode(this.trackNumber, value));
}
/**
* Sets the pan
* @param value A floating-point value between -1 and 1, where -1 is 100% left and 1 is 100% right
*/
setPan(value) {
if (value < -1 || value > 1) {
throw new RangeError('Must be between -1 and 1');
}
this._send(Commands_1.SetTrackPan(this.trackNumber, value));
// Reaper won't send a pan message, but will send pan2 when pan changes
this._pan = value;
}
/**
* Sets the pan 2
* @param value A floating-point value between -1 and 1, where -1 is 100% left and 1 is 100% right
*/
setPan2(value) {
if (value < -1 || value > 1) {
throw new RangeError('Must be between -1 and 1');
}
this._send(Commands_1.SetTrackPan2(this.trackNumber, value));
// Reaper won't send a pan2 message, but will send pan when pan2 changes
this._pan2 = value;
}
/**
* Sets the volume to a specific dB value.
* @param value Value (in dB) to set the volume to. Valid range is -100 to 12.
*/
setVolumeDb(value) {
if (value < -100 || value > 12) {
throw new RangeError('Must be between -100 and 12');
}
this._send(Commands_1.SetTrackVolumeDb(this.trackNumber, value));
// Reaper does not send OSC message to update this, but does send other volume messages
this._volumeDb = value;
}
/** Sets the volume by moving the fader to a specific position
* @param position A value for the fader position between 0 and 1, where 0 is all the way down and 1 is all the way up
*/
setVolumeFaderPosition(position) {
if (position < 0 || position > 1) {
throw new RangeError('Must be between 0 and 1');
}
this._send(Commands_1.SetTrackVolume(this.trackNumber, position));
// Reaper does not send OSC message to update this, but does send other volume messages
this._volumeFaderPosition = position;
}
/** Solo the track */
solo() {
this._send(Commands_1.SetTrackSolo(this.trackNumber, true));
}
/** Toggle mute on/off */
toggleMute() {
this._send(Commands_1.ToggleTrackMute(this.trackNumber));
}
/** Toggle record arm on/off */
toggleRecordArm() {
this._send(Commands_1.ToggleTrackRecordArm(this.trackNumber));
}
/** Toggle solo on/off */
toggleSolo() {
this._send(Commands_1.ToggleTrackSolo(this.trackNumber));
}
/** Unmute the track */
unmute() {
this._send(Commands_1.SetTrackMute(this.trackNumber, false));
}
/** Unsolo the track */
unsolo() {
this._send(Commands_1.SetTrackSolo(this.trackNumber, false));
}
/** The track volume in dB */
get volumeDb() {
return this._volumeDb;
}
/** A floating-point value between 0 and 1 that indicates the fader position, with 0 being all the way down and 1 being all the way up */
get volumeFaderPosition() {
return this._volumeFaderPosition;
}
/** A floating-point value between 0 and 1 that indicates the VU level */
get vu() {
return this._vu;
}
/** A floating-point value between 0 and 1 that indicates the Left VU level */
get vuLeft() {
return this._vuLeft;
}
/** A floating-point value between 0 and 1 that indicates the Right VU level */
get vuRight() {
return this._vuRight;
}
};
__decorate([
Notify_1.notify('isMuted')
], Track.prototype, "_isMuted", void 0);
__decorate([
Notify_1.notify('isRecordArmed')
], Track.prototype, "_isRecordArmed", void 0);
__decorate([
Notify_1.notify('isSelected')
], Track.prototype, "_isSelected", void 0);
__decorate([
Notify_1.notify('isSoloed')
], Track.prototype, "_isSoloed", void 0);
__decorate([
Notify_1.notify('name')
], Track.prototype, "_name", void 0);
__decorate([
Notify_1.notify('pan')
], Track.prototype, "_pan", void 0);
__decorate([
Notify_1.notify('pan2')
], Track.prototype, "_pan2", void 0);
__decorate([
Notify_1.notify('panMode')
], Track.prototype, "_panMode", void 0);
__decorate([
Notify_1.notify('recordMonitoring')
], Track.prototype, "_recordMonitoring", void 0);
__decorate([
Notify_1.notify('volumeDb')
], Track.prototype, "_volumeDb", void 0);
__decorate([
Notify_1.notify('volumeFaderPosition')
], Track.prototype, "_volumeFaderPosition", void 0);
__decorate([
Notify_1.notify('vu')
], Track.prototype, "_vu", void 0);
__decorate([
Notify_1.notify('vuLeft')
], Track.prototype, "_vuLeft", void 0);
__decorate([
Notify_1.notify('vuRight')
], Track.prototype, "_vuRight", void 0);
Track = __decorate([
Notify_1.notifyOnPropertyChanged
], Track);
exports.Track = Track;
//# sourceMappingURL=Tracks.js.map