reaper-osc
Version:
Controls Cockos Reaper using OSC
361 lines • 11.9 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.Beat = exports.Transport = void 0;
/**
* Contains classes for controlling Reaper's transport
* @module
*/
const Notify_1 = require("./Notify");
const Commands_1 = require("./Client/Commands");
const Marker_1 = require("./Marker");
const Region_1 = require("./Region");
/** The Reaper transport */
let Transport = class Transport {
/**
* @param send A callback used to send typed commands to Reaper
*/
constructor(send) {
this._beat = '1.1.00';
this._frames = '00:00:00:00';
this._isFastForwarding = false;
this._isPaused = false;
this._isPlaying = false;
this._isRecording = false;
this._isRepeatEnabled = false;
this._isRewinding = false;
this._isStopped = false;
this._isRewindByMarker = false;
this._isSetLoop = false;
this._loopEnd = 0;
this._loopStart = 0;
this._time = 0;
this._lastMarker = new Marker_1.LastMarker();
this._lastRegion = new Region_1.LastRegion();
this._send = send;
}
/** Indicates the current transport beat in format mm.bb.xx */
get beat() {
return this._beat;
}
/** Indicates the current transport from in format h:m:s:f */
get frames() {
return this._frames;
}
/** Indicates whether playback is paused */
get isPaused() {
return this._isPaused;
}
/** Indicates whether playback is active */
get isPlaying() {
return this._isPlaying;
}
/** Indicates whether playback is stopped */
get isStopped() {
return this._isStopped;
}
/** Indicates whether recording is active */
get isRecording() {
return this._isRecording;
}
/** Indicates whether rewind is active */
get isRewinding() {
return this._isRewinding;
}
/** Indicates whether fast-foward is active */
get isFastForwarding() {
return this._isFastForwarding;
}
/** Indicates whether repeat is enabled */
get isRepeatEnabled() {
return this._isRepeatEnabled;
}
/** Indicates whether rewind-to-previous-marker is enabled */
get isRewindByMarker() {
return this._isRewindByMarker;
}
/** Indicates whether the set-loop-points mode is enabled */
get isSetLoop() {
return this._isSetLoop;
}
/** The most recently passed marker */
get lastMarker() {
return this._lastMarker;
}
/** The most recently entered region */
get lastRegion() {
return this._lastRegion;
}
/** Indicates the end time of the loop (in seconds) */
get loopEnd() {
return this._loopEnd;
}
/** Indicates the start time of the loop (in seconds) */
get loopStart() {
return this._loopStart;
}
/** Indicates the current transport time in seconds */
get time() {
return this._time;
}
/**
* Handle a typed incoming event
* @param event The event to handle
*/
handleEvent(event) {
switch (event.type) {
case 'transport:repeat':
this._isRepeatEnabled = event.enabled;
break;
case 'transport:record':
this._isRecording = event.recording;
break;
case 'transport:stop':
this._isStopped = event.stopped;
break;
case 'transport:pause':
this._isPaused = event.paused;
break;
case 'transport:play':
this._isPlaying = event.playing;
break;
case 'transport:rewind':
this._isRewinding = event.rewinding;
break;
case 'transport:fastForward':
this._isFastForwarding = event.fastForwarding;
break;
case 'transport:time':
this._time = event.time;
break;
case 'transport:beat':
this._beat = event.beat;
break;
case 'transport:frames':
this._frames = event.frames;
break;
case 'transport:loopStart':
this._loopStart = event.time;
break;
case 'transport:loopEnd':
this._loopEnd = event.time;
break;
case 'transport:rewindByMarker':
this._isRewindByMarker = event.enabled;
break;
case 'transport:setLoop':
this._isSetLoop = event.enabled;
break;
}
this._lastMarker.handleEvent(event);
this._lastRegion.handleEvent(event);
}
/** Jumps to the specified beat (absolute)
* @param beat The beat to jump to
*/
jumpToBeat(beat) {
this._send(Commands_1.SetBeat(beat.toString()));
}
/** Jumps to the specified frame (absolute)
* @param frame Frame to jump to (in format h:m:s:f). Values in an invalid format will be ignored by Reaper
*/
jumpToFrame(frame) {
this._send(Commands_1.SetFrames(frame));
}
/** Jumps to the specified time in seconds (absolute)
* @param time The time to jump to (in seconds). If this value is negative, Reaper will jump to 0
*/
jumpToTime(time) {
this._send(Commands_1.SetTime(time));
}
/**
* Jumps to a relative time in seconds.
* Note that the absolute value to jump to is calculated by the library based on the currently known time,
* as Reaper does not appear to support jumping to a relative time via OSC
* @param time The relative time jump (in seconds)
*/
jumpToTimeRelative(time) {
this._send(Commands_1.SetTime(Math.max(this._time + time, 0)));
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onPropertyChanged(property, callback) {
throw new Error('not implemented');
}
/** Toggle pause */
pause() {
this._send(Commands_1.Pause());
}
/** Toggle play */
play() {
this._send(Commands_1.Play());
}
/** Toggle recording */
record() {
this._send(Commands_1.ToggleRecord());
}
/**
* Sets the loop end time
* @param time End time for the loop (in seconds)
*/
setLoopEnd(time) {
this._send(Commands_1.SetLoopEnd(time));
}
/**
* Sets the loop start time
* @param time Start time for the loop (in seconds)
*/
setLoopStart(time) {
this._send(Commands_1.SetLoopStart(time));
}
/** Start fast fowarding. Will continue until stopped */
startFastForwarding() {
this._send(Commands_1.SetFastForward(true));
}
/** Start rewinding. Will continue until stopped */
startRewinding() {
this._send(Commands_1.SetRewind(true));
}
/** Stop playback or recording */
stop() {
this._send(Commands_1.Stop());
}
/** Stop fast forwarding */
stopFastForwarding() {
this._send(Commands_1.SetFastForward(false));
}
/** Stop rewinding */
stopRewinding() {
this._send(Commands_1.SetRewind(false));
}
/** Toggle repeat on or off */
toggleRepeat() {
this._send(Commands_1.ToggleRepeat());
}
/** Toggle rewind-to-previous-marker on or off */
toggleRewindByMarker() {
this._send(Commands_1.ToggleRewindByMarker());
}
/** Toggle the set-loop-points mode on or off */
toggleSetLoop() {
this._send(Commands_1.ToggleSetLoop());
}
/**
* Jump to the marker with the given user-assigned number (as shown in Reaper's UI).
* @param markerNumber The user-assigned marker number to jump to
*/
gotoMarker(markerNumber) {
this._send(Commands_1.GotoMarker(markerNumber));
}
/**
* Jump to the region with the given user-assigned number (as shown in Reaper's UI).
* @param regionNumber The user-assigned region number to jump to
*/
gotoRegion(regionNumber) {
this._send(Commands_1.GotoRegion(regionNumber));
}
};
__decorate([
Notify_1.notify('beat')
], Transport.prototype, "_beat", void 0);
__decorate([
Notify_1.notify('frames')
], Transport.prototype, "_frames", void 0);
__decorate([
Notify_1.notify('isFastForwarding')
], Transport.prototype, "_isFastForwarding", void 0);
__decorate([
Notify_1.notify('isPaused')
], Transport.prototype, "_isPaused", void 0);
__decorate([
Notify_1.notify('isPlaying')
], Transport.prototype, "_isPlaying", void 0);
__decorate([
Notify_1.notify('isRecording')
], Transport.prototype, "_isRecording", void 0);
__decorate([
Notify_1.notify('isRepeatEnabled')
], Transport.prototype, "_isRepeatEnabled", void 0);
__decorate([
Notify_1.notify('isRewinding')
], Transport.prototype, "_isRewinding", void 0);
__decorate([
Notify_1.notify('isStopped')
], Transport.prototype, "_isStopped", void 0);
__decorate([
Notify_1.notify('isRewindByMarker')
], Transport.prototype, "_isRewindByMarker", void 0);
__decorate([
Notify_1.notify('isSetLoop')
], Transport.prototype, "_isSetLoop", void 0);
__decorate([
Notify_1.notify('loopEnd')
], Transport.prototype, "_loopEnd", void 0);
__decorate([
Notify_1.notify('loopStart')
], Transport.prototype, "_loopStart", void 0);
__decorate([
Notify_1.notify('time')
], Transport.prototype, "_time", void 0);
Transport = __decorate([
Notify_1.notifyOnPropertyChanged
], Transport);
exports.Transport = Transport;
/** Represents a beat value in Reaper */
class Beat {
/**
* @param measure The measure of the beat
* @param beat The beat in the measure
* @param fraction The beat fraction (must be >= 0 and < 100)
*/
constructor(measure, beat, fraction) {
if (fraction < 0 || fraction >= 100) {
throw new Error(`Invalid fraction ${fraction}, must be >= 0 and < 100`);
}
this._beat = beat;
this._fraction = fraction;
this._measure = measure;
}
/** Indicates the beat portion of the beat (mm) */
get beat() {
return this._beat;
}
/** Indicates the fraction portion of the beat (bb) */
get fraction() {
return this._fraction;
}
/** Indicates the measure of the beat (xx) */
get measure() {
return this._measure;
}
/**
* Parses a string into a Beat
* @param value String value in the format mm.bb.xx
* @returns The parsed beat
* @throws Throws an error when the format is invalid
*/
static parse(value) {
const parts = value.split('.');
if (parts.length != 3) {
throw new Error('Must be in the format mm.bb.xx');
}
const numberParts = [];
parts.forEach(element => {
const intValue = parseInt(element);
numberParts.push(intValue);
});
return new Beat(numberParts[0], numberParts[1], numberParts[2]);
}
/**
* Converts the beat into its string representation in the format mm.bb.xx
*/
toString() {
return `${this.measure}.${this.beat}.${this.fraction}`;
}
}
exports.Beat = Beat;
//# sourceMappingURL=Transport.js.map