diff --git a/docs/docs/usage/sections/sources.md b/docs/docs/usage/sections/sources.md index c3e4ead3..8f7993f0 100644 --- a/docs/docs/usage/sections/sources.md +++ b/docs/docs/usage/sections/sources.md @@ -18,6 +18,7 @@ The following source types are supported: * Open Sound Control (OSC) * Panasonic AV-HS410 * Analog Way Livecore Image Processors +* Riedel SimplyLive When you add a source and the connection to the tally source (video switcher, software, etc.) is successfully made, the source will be green. If there is an error, the source will be red. Look at the logs for more error information. @@ -70,3 +71,7 @@ You will need the IP address of the switcher. Multicast must also be enabled on ## Analog Way Livecore Image Processors You will need the IP address of the device, and the port (standard port is 10600). + +## Riedel SimplyLive +You need to configure TSL in the SimplyLive backend to send the data to Tally Arbiter at the port you specify. +Uses an TSL v5 UDP connection internally. \ No newline at end of file diff --git a/src/sources/SimplyLive.ts b/src/sources/SimplyLive.ts new file mode 100644 index 00000000..79e20654 --- /dev/null +++ b/src/sources/SimplyLive.ts @@ -0,0 +1,61 @@ +import {RegisterTallyInput} from "../_decorators/RegisterTallyInput.decorator"; +import {FreePort, UsePort} from "../_decorators/UsesPort.decorator"; +import {Source} from '../_models/Source'; +import {TallyInputConfigField} from "../_types/TallyInputConfigField"; +import {TallyInput} from './_Source'; +import dgram from "dgram"; +import {TSL5DataParser} from "./TSL"; + +const SimplyLiveFields: TallyInputConfigField[] = [{fieldName: 'port', fieldLabel: 'Port', fieldType: 'port'}]; + +@RegisterTallyInput("4bbae5b31", "SimplyLive", "", SimplyLiveFields) +export class SimplyLivePSource extends TallyInput { + private server: any; + + constructor(source: Source) { + super(source); + let port = source.data.port; + + UsePort(port, this.source.id); + this.server = dgram.createSocket('udp4'); + this.server.bind(port); + + this.server.on('message', (message) => { + if (message.length > 12) { + let tallyobj: any = TSL5DataParser.parseTSL5Data(message) + this.renameAddress(tallyobj.INDEX[0].toString(), tallyobj.INDEX[0].toString(), tallyobj.TEXT.toString().trim()); + + let inPreview: number = 0; + let inProgram: number = 0; + + if (tallyobj.control.rh_tally !== 0) { + inPreview = 1 + } + if (tallyobj.control.lh_tally !== 0) { + inProgram = 1 + } + + const busses: string[] = []; + if (inPreview) { + busses.push("preview"); + } + if (inProgram) { + busses.push("program"); + } + + this.setBussesForAddress(tallyobj.INDEX[0].toString(), busses); + this.sendIndividualTallyData(tallyobj.INDEX[0].toString(), busses); + } + }); + + + this.connected.next(true); + } + + public exit(): void { + super.exit(); + this.server.close(); + FreePort(this.source.data.port, this.source.id); + this.connected.next(false); + } +} \ No newline at end of file diff --git a/src/sources/TSL.ts b/src/sources/TSL.ts index 12cd16c0..80c41681 100644 --- a/src/sources/TSL.ts +++ b/src/sources/TSL.ts @@ -1,4 +1,3 @@ -import { logger } from ".."; import { RegisterTallyInput } from "../_decorators/RegisterTallyInput.decorator"; import { FreePort, UsePort } from "../_decorators/UsesPort.decorator"; import { Source } from '../_models/Source'; @@ -133,55 +132,61 @@ export class TSL3TCPSource extends TallyInput { } } -class TSL5Base extends TallyInput { - protected processTSL5Tally(data) { - if (data.length > 12) { +export class TSL5DataParser { + public static parseTSL5Data(data) { + let tallyobj: any = {}; - let tallyobj: any = {}; + var cursor = 0; - var cursor = 0; + //Message Format + const _PBC = 2 //bytes + const _VAR = 1 + const _FLAGS = 1 + const _SCREEN = 2 + const _INDEX = 2 + const _CONTROL = 2 - //Message Format - const _PBC = 2 //bytes - const _VAR = 1 - const _FLAGS = 1 - const _SCREEN = 2 - const _INDEX = 2 - const _CONTROL = 2 + //Display Data + const _LENGTH = 2 - //Display Data - const _LENGTH = 2 + tallyobj.PBC = jspack.Unpack("> 0 & 0b11); + tallyobj.control.text_tally = (tallyobj.CONTROL >> 2 & 0b11); + tallyobj.control.lh_tally = (tallyobj.CONTROL >> 4 & 0b11); + tallyobj.control.brightness = (tallyobj.CONTROL >> 6 & 0b11); + tallyobj.control.reserved = (tallyobj.CONTROL >> 8 & 0b1111111); + tallyobj.control.control_data = (tallyobj.CONTROL >> 15 & 0b1); - tallyobj.control = {}; - tallyobj.control.rh_tally = (tallyobj.CONTROL >> 0 & 0b11); - tallyobj.control.text_tally = (tallyobj.CONTROL >> 2 & 0b11); - tallyobj.control.lh_tally = (tallyobj.CONTROL >> 4 & 0b11); - tallyobj.control.brightness = (tallyobj.CONTROL >> 6 & 0b11); - tallyobj.control.reserved = (tallyobj.CONTROL >> 8 & 0b1111111); - tallyobj.control.control_data = (tallyobj.CONTROL >> 15 & 0b1); + var LENGTH = jspack.Unpack(" 12) { + let tallyobj: any = TSL5DataParser.parseTSL5Data(data) this.renameAddress(tallyobj.INDEX[0].toString(), tallyobj.INDEX[0].toString(), tallyobj.TEXT.toString().trim());