diff --git a/src/atem.ts b/src/atem.ts index 01bdb9858..9efa19c9c 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -38,6 +38,7 @@ import { FairlightAudioExpanderState, FairlightAudioRoutingSource, FairlightAudioRoutingOutput, + FairlightAudioMonitorSolo, } from './state/fairlight' import { FairlightDynamicsResetProps } from './commands/Fairlight/common' import { MultiViewerPropertiesState } from './state/settings' @@ -936,6 +937,14 @@ export class Atem extends BasicAtem { return this.sendCommand(command) } + public async setFairlightAudioMixerMonitorSolo( + props: Partial> + ): Promise { + const command = new Commands.FairlightMixerMonitorSoloCommand() + command.updateProps(props) + return this.sendCommand(command) + } + public async setFairlightAudioMixerInputProps( index: number, props: Commands.FairlightMixerInputCommand['properties'] diff --git a/src/commands/Fairlight/FairlightMixerMonitorCommand.ts b/src/commands/Fairlight/FairlightMixerMonitorCommand.ts index 0195d9717..34cab5572 100644 --- a/src/commands/Fairlight/FairlightMixerMonitorCommand.ts +++ b/src/commands/Fairlight/FairlightMixerMonitorCommand.ts @@ -9,6 +9,7 @@ export class FairlightMixerMonitorCommand extends WritableCommand> { + public static MaskFlags = { + solo: 1 << 0, + index: 1 << 1, + source: 1 << 1, // Intentional duplicate + } + + public static readonly rawName = 'CFMS' + + public serialize(): Buffer { + const buffer = Buffer.alloc(24) + buffer.writeUInt8(this.flag, 0) + + buffer.writeUInt8(this.properties.solo ? 1 : 0, 1) + buffer.writeUInt16BE(this.properties.index ?? 0, 8) + if (this.properties.source) buffer.writeBigInt64BE(BigInt(this.properties.source), 16) + return buffer + } +} + +export class FairlightMixerMonitorSoloUpdateCommand extends DeserializedCommand { + public static readonly rawName = 'FAMS' + + public static deserialize(rawCommand: Buffer): FairlightMixerMonitorSoloUpdateCommand { + const properties: FairlightAudioMonitorSolo = { + solo: rawCommand.readUint8(0) === 1, + index: rawCommand.readUInt16BE(8), + source: rawCommand.readBigInt64BE(16).toString(), + } + + return new FairlightMixerMonitorSoloUpdateCommand(properties) + } + + public applyToState(state: AtemState): string { + if (!state.fairlight) { + throw new InvalidIdError('Fairlight') + } + + state.fairlight.solo = { ...this.properties } + + return `fairlight.solo` + } +} diff --git a/src/commands/Fairlight/index.ts b/src/commands/Fairlight/index.ts index aa9f8dadf..fd9ccfe98 100644 --- a/src/commands/Fairlight/index.ts +++ b/src/commands/Fairlight/index.ts @@ -11,7 +11,7 @@ export * from './FairlightMixerMasterLevelsCommand' export * from './FairlightMixerMasterLimiterCommand' export * from './FairlightMixerMasterPropertiesCommand' export * from './FairlightMixerMonitorCommand' -// export * from './FairlightMixerMonitorSoloCommand' +export * from './FairlightMixerMonitorSoloCommand' export * from './FairlightMixerResetPeakLevelsCommand' export * from './FairlightMixerSendLevelsCommand' export * from './FairlightMixerSourceCommand' diff --git a/src/state/fairlight.ts b/src/state/fairlight.ts index 41d9cc887..c46b328f1 100644 --- a/src/state/fairlight.ts +++ b/src/state/fairlight.ts @@ -78,7 +78,15 @@ export interface FairlightAudioMonitorChannel { inputMasterGain: number inputMasterMuted: boolean inputTalkbackGain: number + inputTalkbackMuted: boolean inputSidetoneGain: number + // inputSidetoneMuted: boolean +} + +export interface FairlightAudioMonitorSolo { + solo: boolean + index: number + source: string } export interface FairlightAudioSource { @@ -162,6 +170,7 @@ export interface AtemFairlightAudioState { inputs: { [input: number]: FairlightAudioInput | undefined } master?: FairlightAudioMasterChannel monitor?: FairlightAudioMonitorChannel + solo?: FairlightAudioMonitorSolo audioFollowVideoCrossfadeTransitionEnabled?: boolean