UNPKG

timeline-state-resolver

Version:
255 lines • 14.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.VMixTimelineStateConverter = void 0; const timeline_state_resolver_types_1 = require("timeline-state-resolver-types"); const vMixStateDiffer_1 = require("./vMixStateDiffer"); const deepMerge = require("deepmerge"); const _ = require("underscore"); const mappingPriority = { [timeline_state_resolver_types_1.MappingVmixType.Program]: 0, [timeline_state_resolver_types_1.MappingVmixType.Preview]: 1, [timeline_state_resolver_types_1.MappingVmixType.Input]: 2, [timeline_state_resolver_types_1.MappingVmixType.AudioChannel]: 3, [timeline_state_resolver_types_1.MappingVmixType.Output]: 4, [timeline_state_resolver_types_1.MappingVmixType.Overlay]: 5, [timeline_state_resolver_types_1.MappingVmixType.Recording]: 6, [timeline_state_resolver_types_1.MappingVmixType.Streaming]: 7, [timeline_state_resolver_types_1.MappingVmixType.External]: 8, [timeline_state_resolver_types_1.MappingVmixType.FadeToBlack]: 9, [timeline_state_resolver_types_1.MappingVmixType.Fader]: 10, [timeline_state_resolver_types_1.MappingVmixType.Script]: 11, }; /** * Converts timeline state, to a TSR representation */ class VMixTimelineStateConverter { constructor(getDefaultState, getDefaultInputState, getDefaultInputAudioState) { this.getDefaultState = getDefaultState; this.getDefaultInputState = getDefaultInputState; this.getDefaultInputAudioState = getDefaultInputAudioState; } getVMixStateFromTimelineState(state, mappings) { const deviceState = this._fillStateWithMappingsDefaults(this.getDefaultState(), mappings); // Sort layer based on Mapping type (to make sure audio is after inputs) and Layer name const sortedLayers = _.sortBy(_.map(state.layers, (tlObject, layerName) => ({ layerName, tlObject, mapping: mappings[layerName], })).sort((a, b) => a.layerName.localeCompare(b.layerName)), (o) => mappingPriority[o.mapping.options.mappingType] ?? Number.POSITIVE_INFINITY); _.each(sortedLayers, ({ tlObject, layerName, mapping }) => { const content = tlObject.content; if (mapping && content.deviceType === timeline_state_resolver_types_1.DeviceType.VMIX) { switch (mapping.options.mappingType) { case timeline_state_resolver_types_1.MappingVmixType.Program: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.PROGRAM) { const mixProgram = (mapping.options.index || 1) - 1; if (content.input !== undefined) { this._switchToInput(content.input, deviceState, mixProgram, content.transition); } else if (content.inputLayer) { this._switchToInput(content.inputLayer, deviceState, mixProgram, content.transition, true); } else if (content.transition) { const mixState = deviceState.reportedState.mixes[mixProgram]; if (mixState) { mixState.transition = content.transition; } } } break; case timeline_state_resolver_types_1.MappingVmixType.Preview: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.PREVIEW) { const mixPreview = (mapping.options.index || 1) - 1; const mixState = deviceState.reportedState.mixes[mixPreview]; if (mixState != null && content.input != null) mixState.preview = content.input; } break; case timeline_state_resolver_types_1.MappingVmixType.AudioChannel: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.AUDIO) { const filteredVMixTlAudio = _.pick(content, 'volume', 'balance', 'audioAuto', 'audioBuses', 'muted', 'fade'); if (mapping.options.index) { deviceState.reportedState = this._modifyInputAudio(deviceState, filteredVMixTlAudio, { key: mapping.options.index, }); } else if (mapping.options.inputLayer) { deviceState.reportedState = this._modifyInputAudio(deviceState, filteredVMixTlAudio, { layer: mapping.options.inputLayer, }); } } break; case timeline_state_resolver_types_1.MappingVmixType.Fader: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.FADER) { deviceState.reportedState.faderPosition = content.position; } break; case timeline_state_resolver_types_1.MappingVmixType.Recording: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.RECORDING) { deviceState.reportedState.recording = content.on; } break; case timeline_state_resolver_types_1.MappingVmixType.Streaming: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.STREAMING) { deviceState.reportedState.streaming = content.on; } break; case timeline_state_resolver_types_1.MappingVmixType.External: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.EXTERNAL) { deviceState.reportedState.external = content.on; } break; case timeline_state_resolver_types_1.MappingVmixType.FadeToBlack: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.FADE_TO_BLACK) { deviceState.reportedState.fadeToBlack = content.on; } break; case timeline_state_resolver_types_1.MappingVmixType.Input: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.INPUT) { deviceState.reportedState = this._modifyInput(deviceState, { type: content.inputType, playing: content.playing, loop: content.loop, position: content.seek, transform: content.transform, layers: content.layers ?? (content.overlays ? this._convertDeprecatedInputOverlays(content.overlays) : undefined), listFilePaths: content.listFilePaths, restart: content.restart, text: content.text, url: content.url, index: content.index, images: content.images, }, { key: mapping.options.index, filePath: content.filePath }, layerName); } break; case timeline_state_resolver_types_1.MappingVmixType.Output: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.OUTPUT) { deviceState.outputs[mapping.options.index] = { source: content.source, input: content.input, }; } break; case timeline_state_resolver_types_1.MappingVmixType.Overlay: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.OVERLAY) { const overlayIndex = mapping.options.index - 1; const overlayState = deviceState.reportedState.overlays[overlayIndex]; if (overlayState != null) { overlayState.input = content.input; } } break; case timeline_state_resolver_types_1.MappingVmixType.Script: if (content.type === timeline_state_resolver_types_1.TimelineContentTypeVMix.SCRIPT) { deviceState.runningScripts.push(content.name); } break; } } }); return deviceState; } _modifyInput(deviceState, newInput, input, layerName) { let inputs = deviceState.reportedState.existingInputs; const filteredNewInput = _.pick(newInput, (x) => x !== undefined); let inputKey; if (input.layer) { inputKey = deviceState.inputLayers[input.layer]; inputs = deviceState.reportedState.inputsAddedByUs; } else if (input.filePath) { inputKey = vMixStateDiffer_1.TSR_INPUT_PREFIX + input.filePath; inputs = deviceState.reportedState.inputsAddedByUs; } else { inputKey = input.key; } if (inputKey) { inputs[inputKey] = deepMerge(inputs[inputKey] ?? this.getDefaultInputState(inputKey), filteredNewInput); deviceState.inputLayers[layerName] = inputKey; } return deviceState.reportedState; } _modifyInputAudio(deviceState, newInput, input) { let inputs = deviceState.reportedState.existingInputsAudio; const filteredNewInput = _.pick(newInput, (x) => x !== undefined); let inputKey; if (input.layer) { inputKey = deviceState.inputLayers[input.layer]; inputs = deviceState.reportedState.inputsAddedByUsAudio; } else { inputKey = input.key; } if (inputKey) { inputs[inputKey] = deepMerge(inputs[inputKey] ?? this.getDefaultInputAudioState(inputKey), filteredNewInput); } return deviceState.reportedState; } _switchToInput(input, deviceState, mix, transition, layerToProgram = false) { const mixState = deviceState.reportedState.mixes[mix]; if (mixState == null) return; if (mixState.program === undefined || mixState.program !== input // mixing numeric and string input names can be dangerous ) { mixState.preview = mixState.program; mixState.program = input; mixState.transition = transition ?? { effect: timeline_state_resolver_types_1.VMixTransitionType.Cut, duration: 0 }; mixState.layerToProgram = layerToProgram; } } _fillStateWithMappingsDefaults(state, mappings) { for (const mapping of Object.values(mappings)) { switch (mapping.options.mappingType) { case timeline_state_resolver_types_1.MappingVmixType.Program: case timeline_state_resolver_types_1.MappingVmixType.Preview: { const mixProgram = mapping.options.index || 1; state.reportedState.mixes[mixProgram - 1] = { number: mixProgram, preview: undefined, program: undefined, transition: { effect: timeline_state_resolver_types_1.VMixTransitionType.Cut, duration: 0 }, }; break; } case timeline_state_resolver_types_1.MappingVmixType.Input: if (mapping.options.index) { state.reportedState.existingInputs[mapping.options.index] = this.getDefaultInputState(mapping.options.index); } break; case timeline_state_resolver_types_1.MappingVmixType.AudioChannel: if (mapping.options.index) { state.reportedState.existingInputsAudio[mapping.options.index] = this.getDefaultInputAudioState(mapping.options.index); } break; case timeline_state_resolver_types_1.MappingVmixType.Recording: state.reportedState.recording = false; break; case timeline_state_resolver_types_1.MappingVmixType.Streaming: state.reportedState.streaming = false; break; case timeline_state_resolver_types_1.MappingVmixType.External: state.reportedState.external = false; break; case timeline_state_resolver_types_1.MappingVmixType.Output: state.outputs[mapping.options.index] = { source: 'Program' }; break; case timeline_state_resolver_types_1.MappingVmixType.Overlay: state.reportedState.overlays[mapping.options.index - 1] = { number: mapping.options.index, input: undefined, }; break; } } return state; } _convertDeprecatedInputOverlays(overlays) { return _.mapObject(overlays, (value) => ({ input: value })); } } exports.VMixTimelineStateConverter = VMixTimelineStateConverter; //# sourceMappingURL=vMixTimelineStateConverter.js.map