mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-14 03:43:50 +00:00
147 lines
4.0 KiB
TypeScript
147 lines
4.0 KiB
TypeScript
import { ArgumentType, Client, Message } from 'node-osc';
|
|
import { LogOrigin, MaybeNumber, MaybeString, OSCSettings, OscSubscription } from 'ontime-types';
|
|
|
|
import IIntegration, { TimerLifeCycleKey } from './IIntegration.js';
|
|
import { parseTemplateNested } from './integrationUtils.js';
|
|
import { logger } from '../../classes/Logger.js';
|
|
import { OscServer } from '../../adapters/OscAdapter.js';
|
|
import { stringToOSCArgs } from '../../utils/oscArgParser.js';
|
|
|
|
/**
|
|
* @description Class contains logic towards outgoing OSC communications
|
|
* @class
|
|
*/
|
|
export class OscIntegration implements IIntegration<OscSubscription, OSCSettings> {
|
|
protected oscClient: null | Client;
|
|
protected oscServer: OscServer | null = null;
|
|
|
|
subscriptions: OscSubscription[];
|
|
targetIP: MaybeString;
|
|
portOut: MaybeNumber;
|
|
portIn: MaybeNumber;
|
|
enabledOut: boolean;
|
|
enabledIn: boolean;
|
|
|
|
constructor() {
|
|
this.oscClient = null;
|
|
this.subscriptions = [];
|
|
this.targetIP = null;
|
|
this.portOut = null;
|
|
this.portIn = null;
|
|
this.enabledOut = false;
|
|
this.enabledIn = false;
|
|
}
|
|
|
|
/**
|
|
* Initializes oscClient
|
|
*/
|
|
init(config: OSCSettings) {
|
|
const { targetIP, portOut, subscriptions, enabledOut, enabledIn, portIn } = config;
|
|
|
|
this.initTX(enabledOut, targetIP, portOut, subscriptions);
|
|
this.initRX(enabledIn, portIn);
|
|
// return `OSC integration client connected to ${targetIP}:${portOut}`;
|
|
}
|
|
|
|
private initSubscriptions(subscriptions: OscSubscription[]) {
|
|
this.subscriptions = subscriptions;
|
|
}
|
|
|
|
dispatch(action: TimerLifeCycleKey, state?: object) {
|
|
// noop
|
|
if (!this.oscClient || !this.enabledOut) {
|
|
return;
|
|
}
|
|
|
|
for (let i = 0; i < this.subscriptions.length; i++) {
|
|
const { cycle, address, payload, enabled } = this.subscriptions[i];
|
|
if (cycle !== action || !enabled || !address) {
|
|
continue;
|
|
}
|
|
const parsedAddress = parseTemplateNested(address, state || {});
|
|
const parsedPayload = payload ? parseTemplateNested(payload, state || {}) : undefined;
|
|
const parsedArguments = stringToOSCArgs(parsedPayload);
|
|
|
|
try {
|
|
this.emit(parsedAddress, parsedArguments);
|
|
} catch (error) {
|
|
logger.error(LogOrigin.Tx, `OSC Integration: ${error}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
emit(address: string, args: ArgumentType[]) {
|
|
if (!this.oscClient) {
|
|
return;
|
|
}
|
|
|
|
//TODO: Look into using bundles
|
|
const message = new Message(address);
|
|
message.append(args);
|
|
|
|
this.oscClient.send(message);
|
|
}
|
|
|
|
private initTX(enabledOut: boolean, targetIP: string, portOut: number, subscriptions: OscSubscription[]) {
|
|
this.initSubscriptions(subscriptions);
|
|
|
|
if (!enabledOut && this.enabledOut) {
|
|
this.targetIP = targetIP;
|
|
this.portOut = portOut;
|
|
this.enabledOut = enabledOut;
|
|
this.shutdownTX();
|
|
return;
|
|
}
|
|
|
|
if (this.oscClient && targetIP === this.targetIP && portOut === this.portOut) {
|
|
// nothing changed that would mean we need a new client
|
|
return;
|
|
}
|
|
|
|
this.targetIP = targetIP;
|
|
this.portOut = portOut;
|
|
this.enabledOut = enabledOut;
|
|
|
|
try {
|
|
this.oscClient = new Client(targetIP, portOut);
|
|
} catch (error) {
|
|
this.oscClient = null;
|
|
throw new Error(`Failed initialising OSC client: ${error}`);
|
|
}
|
|
}
|
|
|
|
private initRX(enabledIn: boolean, portIn: number) {
|
|
if (!enabledIn && this.enabledIn) {
|
|
this.shutdownRX();
|
|
return;
|
|
}
|
|
|
|
// Start OSC Server
|
|
logger.info(LogOrigin.Rx, `Starting OSC Server on port: ${portIn}`);
|
|
this.oscServer = new OscServer(portIn);
|
|
}
|
|
|
|
shutdown() {
|
|
this.shutdownTX();
|
|
this.shutdownRX();
|
|
}
|
|
|
|
private shutdownTX() {
|
|
logger.info(LogOrigin.Rx, 'Shutting down OSC integration');
|
|
if (this.oscServer) {
|
|
this.oscServer?.shutdown();
|
|
this.oscServer = null;
|
|
}
|
|
}
|
|
|
|
private shutdownRX() {
|
|
logger.info(LogOrigin.Tx, 'Shutting down OSC integration');
|
|
if (this.oscClient) {
|
|
this.oscClient?.close();
|
|
this.oscClient = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
export const oscIntegration = new OscIntegration();
|