diff --git a/packages/blueprints/src/base/showstyle/applyconfig/layers.ts b/packages/blueprints/src/base/showstyle/applyconfig/layers.ts index c9207ec4a..b6a57de19 100644 --- a/packages/blueprints/src/base/showstyle/applyconfig/layers.ts +++ b/packages/blueprints/src/base/showstyle/applyconfig/layers.ts @@ -8,6 +8,11 @@ export enum SourceLayer { DVE_RETAIN = 'dveRetain', GFX = 'gfx', + OGrafFullScreen = 'ograf_fullscreen', + OGrafOverlay1 = 'ograf_overlay1', + OGrafOverlay2 = 'ograf_overlay2', + OGrafOverlay3 = 'ograf_overlay3', + AudioBed = 'audioBed', StudioGuests = 'guest', HostOverride = 'hostOverride', @@ -31,6 +36,9 @@ export function getOutputLayerForSourceLayer(layer: SourceLayer): OutputLayer { switch (layer) { case SourceLayer.Script: return OutputLayer.Script + case SourceLayer.OGrafOverlay1: + case SourceLayer.OGrafOverlay2: + case SourceLayer.OGrafOverlay3: case SourceLayer.LowerThird: case SourceLayer.Strap: case SourceLayer.Ticker: diff --git a/packages/blueprints/src/base/showstyle/applyconfig/sourcelayers.ts b/packages/blueprints/src/base/showstyle/applyconfig/sourcelayers.ts index b904a0615..dd64517cf 100644 --- a/packages/blueprints/src/base/showstyle/applyconfig/sourcelayers.ts +++ b/packages/blueprints/src/base/showstyle/applyconfig/sourcelayers.ts @@ -66,6 +66,34 @@ export function getSourceLayer(): ISourceLayer[] { exclusiveGroup: 'pgm', onPresenterScreen: true, }, + { + _id: SourceLayer.OGrafFullScreen, + type: SourceLayerType.GRAPHICS, + _rank: 110, + name: 'OGraf Full Screen', + abbreviation: 'GFX FULL', + }, + { + _id: SourceLayer.OGrafOverlay1, + type: SourceLayerType.GRAPHICS, + _rank: 111, + name: 'OGraf Overlay 1', + abbreviation: 'GFX1', + }, + { + _id: SourceLayer.OGrafOverlay2, + type: SourceLayerType.GRAPHICS, + _rank: 112, + name: 'OGraf Overlay 2', + abbreviation: 'GFX2', + }, + { + _id: SourceLayer.OGrafOverlay3, + type: SourceLayerType.GRAPHICS, + _rank: 113, + name: 'OGraf Overlay 3', + abbreviation: 'GFX3', + }, { _id: SourceLayer.LowerThird, diff --git a/packages/blueprints/src/base/showstyle/applyconfig/triggered-actions.ts b/packages/blueprints/src/base/showstyle/applyconfig/triggered-actions.ts index db061b018..c4b912fe9 100644 --- a/packages/blueprints/src/base/showstyle/applyconfig/triggered-actions.ts +++ b/packages/blueprints/src/base/showstyle/applyconfig/triggered-actions.ts @@ -45,7 +45,19 @@ export function getTriggeredActions(): IBlueprintTriggeredActions[] { ), ...['F8'].map((key, i) => createAdLibHotkey(key, [SourceLayer.DVE], true, i, undefined)), ...['KeyQ', 'KeyW', 'KeyE', 'KeyR', 'KeyT', 'KeyY'].map((key, i) => - createAdLibHotkey(key, [SourceLayer.LowerThird, SourceLayer.LowerThird, SourceLayer.Ticker], false, i, undefined) + createAdLibHotkey( + key, + [ + SourceLayer.LowerThird, + SourceLayer.Ticker, + SourceLayer.OGrafOverlay1, + SourceLayer.OGrafOverlay2, + SourceLayer.OGrafOverlay3, + ], + false, + i, + undefined + ) ), ...['KeyV', 'Shift+KeyV'].map((key, i) => createAdLibHotkey(key, [SourceLayer.HostOverride], true, i, undefined)), createAdLibHotkeyWithTriggerMode(rankCounter), diff --git a/packages/blueprints/src/base/showstyle/executeActions/actionDefinitions.ts b/packages/blueprints/src/base/showstyle/executeActions/actionDefinitions.ts index 1cc62ef61..733e78b2c 100644 --- a/packages/blueprints/src/base/showstyle/executeActions/actionDefinitions.ts +++ b/packages/blueprints/src/base/showstyle/executeActions/actionDefinitions.ts @@ -2,4 +2,5 @@ export enum ActionId { LastRemote = 'lastRemote', LastDVE = 'lastDVE', GFXStep = 'GFXStep', + OGrafClear = 'ograf-clear', } diff --git a/packages/blueprints/src/base/showstyle/executeActions/index.ts b/packages/blueprints/src/base/showstyle/executeActions/index.ts index 4851fab3e..b6959521f 100644 --- a/packages/blueprints/src/base/showstyle/executeActions/index.ts +++ b/packages/blueprints/src/base/showstyle/executeActions/index.ts @@ -7,6 +7,7 @@ import { import { ActionId } from './actionDefinitions.js' import { SourceLayer } from '../applyconfig/layers.js' import { ExampleGFXStepActionOptions, executeGraphicNextStep } from './steppedGraphicExample.js' +import { executeOGrafClear } from './ograf.js' export async function executeAction( context: IActionExecutionContext, @@ -40,6 +41,8 @@ export async function executeAction( await executeLastOnSourceLayer(context, SourceLayer.DVE) } else if (actionId === ActionId.GFXStep) { await executeGraphicNextStep(context, triggerMode, actionOptions as ExampleGFXStepActionOptions) + } else if (actionId === ActionId.OGrafClear) { + await executeOGrafClear(context) } } diff --git a/packages/blueprints/src/base/showstyle/executeActions/ograf.ts b/packages/blueprints/src/base/showstyle/executeActions/ograf.ts new file mode 100644 index 000000000..677702d02 --- /dev/null +++ b/packages/blueprints/src/base/showstyle/executeActions/ograf.ts @@ -0,0 +1,6 @@ +import { IActionExecutionContext } from '@sofie-automation/blueprints-integration' +import { SourceLayer } from '../applyconfig/layers.js' + +export async function executeOGrafClear(context: IActionExecutionContext): Promise { + await context.stopPiecesOnLayers([SourceLayer.OGrafOverlay1, SourceLayer.OGrafOverlay2, SourceLayer.OGrafOverlay3]) +} diff --git a/packages/blueprints/src/base/showstyle/helpers/ograf-graphics.ts b/packages/blueprints/src/base/showstyle/helpers/ograf-graphics.ts new file mode 100644 index 000000000..da644b433 --- /dev/null +++ b/packages/blueprints/src/base/showstyle/helpers/ograf-graphics.ts @@ -0,0 +1,153 @@ +import { IBlueprintAdLibPiece, IBlueprintPiece, PieceLifespan, TSR } from '@sofie-automation/blueprints-integration' +import { ObjectType, OGrafGraphicObject, SomeObject } from '../../../common/definitions/objects.js' +import { literal } from '../../../common/util.js' +import { StudioConfig } from '../../studio/helpers/config.js' +import { OGrafLayers } from '../../studio/layers.js' +import { getOutputLayerForSourceLayer, SourceLayer } from '../applyconfig/layers.js' +import { getClipPlayerInput } from './clips.js' +import { createVisionMixerObjects } from './visionMixer.js' +import { TimelineBlueprintExt } from '../../studio/customTypes.js' +import { GraphicsResult } from './graphics.js' + +export function parseOGrafGraphicsFromObjects(config: StudioConfig, objects: SomeObject[]): GraphicsResult { + const graphicsObjects = objects.filter((o): o is OGrafGraphicObject => o.objectType === ObjectType.OGrafGraphic) + + return { + pieces: graphicsObjects.filter((o) => !o.isAdlib).map((o) => parseOGrafGraphic(config, o)), + adLibPieces: graphicsObjects.filter((o) => Boolean(o.isAdlib)).map((o, i) => parseAdlibOGrafGraphic(config, o, i)), + } +} + +function parseOGrafGraphic(config: StudioConfig, object: OGrafGraphicObject): IBlueprintPiece { + const sourceLayer = getSourceLayer(object) + + return { + externalId: object.id, + name: makeOGrafName(object), + lifespan: PieceLifespan.WithinPart, + sourceLayerId: sourceLayer, + outputLayerId: getOutputLayerForSourceLayer(sourceLayer), + content: { + timelineObjects: getGraphicTlObject(config, object, false), + + previewRenderer: config.previewRenderer, + }, + enable: { + start: object.objectTime ?? 0, + duration: object.duration > 0 ? object.duration : undefined, + }, + prerollDuration: config.casparcgLatency, + } +} +function parseAdlibOGrafGraphic(config: StudioConfig, object: OGrafGraphicObject, index: number): IBlueprintAdLibPiece { + const sourceLayer = getSourceLayer(object) + + return { + externalId: object.id, + name: makeOGrafName(object), + lifespan: PieceLifespan.WithinPart, + sourceLayerId: sourceLayer, + outputLayerId: getOutputLayerForSourceLayer(sourceLayer), + content: { + timelineObjects: getGraphicTlObject(config, object, true), + }, + _rank: index, // todo - probably some offset for ordering + expectedDuration: object.duration, + } +} + +function getSourceLayer(object: OGrafGraphicObject): SourceLayer { + switch (object.attributes.type) { + case 'full-screen': + return SourceLayer.OGrafFullScreen + case 'overlay1': + return SourceLayer.OGrafOverlay1 + case 'overlay2': + return SourceLayer.OGrafOverlay2 + case 'overlay3': + return SourceLayer.OGrafOverlay3 + default: + return SourceLayer.OGrafOverlay1 + } +} +function getGraphicTlLayer(object: OGrafGraphicObject): OGrafLayers { + switch (object.attributes.type) { + case 'full-screen': + return OGrafLayers.OGrafFullScreen + case 'overlay1': + return OGrafLayers.OGrafOverlay1 + case 'overlay2': + return OGrafLayers.OGrafOverlay2 + case 'overlay3': + return OGrafLayers.OGrafOverlay3 + default: + return OGrafLayers.OGrafOverlay1 + } +} + +function getGraphicTlObject( + config: StudioConfig, + object: OGrafGraphicObject, + isAdlib?: boolean +): TimelineBlueprintExt[] { + const fullscreenAtemInput = getClipPlayerInput(config) + const timelineLayer = getGraphicTlLayer(object) + const isFullscreen = timelineLayer === OGrafLayers.OGrafFullScreen + + return [ + literal>({ + id: '', + enable: { + start: 0, // TODO - this might not be quite right + }, + layer: timelineLayer, + priority: 1 + (isAdlib ? 10 : 0), + content: { + deviceType: TSR.DeviceType.OGRAF, + type: TSR.TimelineContentTypeOgraf.GRAPHIC, + + graphicId: object.attributes['ograf-id'], + playing: true, + + data: object.attributes['ograf-data'], + useStopCommand: true, + }, + }), + ...(isFullscreen ? createVisionMixerObjects(config, fullscreenAtemInput?.input || 0, config.casparcgLatency) : []), + ] +} + +function makeOGrafName(object: OGrafGraphicObject): string { + const data = object.attributes['ograf-data'] || {} + + if (Object.keys(data).length === 0) { + // data is empty + return object.clipName + } + + { + let canUseThis = true + const nameParts: string[] = [] + for (const [key, value] of Object.entries(data)) { + if (typeof value === 'string') { + // omit some values that likely won't be useful to show in the name: + if ( + value.startsWith('#') || // likely a color + value.startsWith('{') // likely json + ) + continue + + nameParts.push(value) + } else if (typeof value === 'number') { + nameParts.push(`${value}`) + } else if (typeof value === 'boolean') { + if (value) nameParts.push(`${key}`) + } else { + canUseThis = false + } + } + if (canUseThis) return `${object.clipName} | ${nameParts.join(', ')}` + } + + return `${object.clipName} | ${JSON.stringify(data)}` +} diff --git a/packages/blueprints/src/base/showstyle/manifest.ts b/packages/blueprints/src/base/showstyle/manifest.ts index 7a2486af8..6b7cc209c 100644 --- a/packages/blueprints/src/base/showstyle/manifest.ts +++ b/packages/blueprints/src/base/showstyle/manifest.ts @@ -16,6 +16,7 @@ import { validateConfig } from './validateConfig.js' import { applyConfig } from './applyconfig/index.js' import * as ConfigSchema from '../../$schemas/main-showstyle-config.json' import { dereferenceSync } from 'dereference-json-schema' +import onRundownActivate from './onRundownActivate.js' export const baseManifest: Omit, 'blueprintId' | 'configPresets'> = { /** The type of this blueprint */ @@ -66,8 +67,8 @@ export const baseManifest: Omit, 'bl */ applyConfig, /** Called when a RundownPlaylist has been activated */ - onRundownActivate: async (_context: IRundownActivationContext) => { - // Noop + onRundownActivate: async (context: IRundownActivationContext) => { + return onRundownActivate(context) }, // Uncomment this to enable config fixup migrations between blueprint versions. // Note: When defined, fixUpConfig must be run after every blueprint upload before diff --git a/packages/blueprints/src/base/showstyle/onRundownActivate.ts b/packages/blueprints/src/base/showstyle/onRundownActivate.ts new file mode 100644 index 000000000..70571414a --- /dev/null +++ b/packages/blueprints/src/base/showstyle/onRundownActivate.ts @@ -0,0 +1,21 @@ +import { IRundownActivationContext } from '@sofie-automation/blueprints-integration' + +export default async function onRundownActivate(_context: IRundownActivationContext): Promise { + // Clear OGraf renderers: + // const mappings = context.getStudioMappings() + // const devices = await context.listPlayoutDevices() + // for (const device of devices) { + // if (device.deviceType === TSR.DeviceType.OGRAF) { + // for (const mapping of Object.values(mappings)) { + // if (mapping.device !== TSR.DeviceType.OGRAF) continue + // if (mapping.deviceId === `${device.deviceId}`) { + // if (mapping.options.mappingType === TSR.MappingOgrafType.RenderTarget) { + // await context.executeTSRAction(device.deviceId, TSR.OgrafActions.ClearGraphics, { + // renderTarget: mapping.options.renderTarget, + // }) + // } + // } + // } + // } + // } +} diff --git a/packages/blueprints/src/base/showstyle/part-adapters/camera.ts b/packages/blueprints/src/base/showstyle/part-adapters/camera.ts index 9c7d8df51..6de3b2037 100644 --- a/packages/blueprints/src/base/showstyle/part-adapters/camera.ts +++ b/packages/blueprints/src/base/showstyle/part-adapters/camera.ts @@ -1,4 +1,9 @@ -import { BlueprintResultPart, IBlueprintPiece, PieceLifespan } from '@sofie-automation/blueprints-integration' +import { + BlueprintResultPart, + IBlueprintAdLibPiece, + IBlueprintPiece, + PieceLifespan, +} from '@sofie-automation/blueprints-integration' import { PartContext } from '../../../common/context.js' import { ObjectType, StudioGuestObject } from '../../../common/definitions/objects.js' import { literal } from '../../../common/util.js' @@ -13,6 +18,7 @@ import { getSourceInfoFromRaw } from '../helpers/sources.js' import { createVisionMixerObjects } from '../helpers/visionMixer.js' import { getOutputLayerForSourceLayer, SourceLayer } from '../applyconfig/layers.js' import { parseConfig } from '../helpers/config.js' +import { parseOGrafGraphicsFromObjects } from '../helpers/ograf-graphics.js' export function generateCameraPart(context: PartContext, part: PartProps): BlueprintResultPart { const config = parseConfig(context).studio @@ -40,6 +46,8 @@ export function generateCameraPart(context: PartContext, part: PartProps) const graphics = parseGraphicsFromObjects(config, part.objects) if (graphics.pieces) pieces.push(...graphics.pieces) + const ografGraphics = parseOGrafGraphicsFromObjects(config, part.objects) + if (ografGraphics.pieces) pieces.push(...ografGraphics.pieces) const clips = parseClipsFromObjects(context, config, part.objects) @@ -230,7 +233,7 @@ export function generateDVEPart(context: PartContext, part: PartProps) expectedDuration: part.payload.duration, }, pieces, - adLibPieces: [...graphics.adLibPieces, ...clips], + adLibPieces: [...graphics.adLibPieces, ...clips, ...ografGraphics.adLibPieces], actions: [], } } diff --git a/packages/blueprints/src/base/showstyle/part-adapters/gfx.ts b/packages/blueprints/src/base/showstyle/part-adapters/gfx.ts index 4b26be739..a787f19a6 100644 --- a/packages/blueprints/src/base/showstyle/part-adapters/gfx.ts +++ b/packages/blueprints/src/base/showstyle/part-adapters/gfx.ts @@ -5,11 +5,15 @@ import { parseClipsFromObjects } from '../helpers/clips.js' import { parseGraphicsFromObjects } from '../helpers/graphics.js' import { createScriptPiece } from '../helpers/script.js' import { parseConfig } from '../helpers/config.js' +import { parseOGrafGraphicsFromObjects } from '../helpers/ograf-graphics.js' export function generateGfxPart(context: PartContext, part: PartProps): BlueprintResultPart { const config = parseConfig(context).studio - const graphic = parseGraphicsFromObjects(config, [part.payload.graphic]) + let graphic = parseGraphicsFromObjects(config, [part.payload.graphic]) + if (!graphic.pieces[0]) { + graphic = parseOGrafGraphicsFromObjects(config, [part.payload.graphic]) + } if (!graphic.pieces[0]) context.notifyUserError('Missing fullscreen graphic') const fullscreenPiece = graphic.pieces[0] @@ -20,6 +24,8 @@ export function generateGfxPart(context: PartContext, part: PartProps) const graphics = parseGraphicsFromObjects(config, part.objects) if (graphics.pieces) pieces.push(...graphics.pieces) + const ografGraphics = parseOGrafGraphicsFromObjects(config, part.objects) + if (ografGraphics.pieces) pieces.push(...ografGraphics.pieces) const clips = parseClipsFromObjects(context, config, part.objects) @@ -32,7 +38,7 @@ export function generateGfxPart(context: PartContext, part: PartProps) autoNext: true, }, pieces, - adLibPieces: [...graphics.adLibPieces, ...clips], + adLibPieces: [...graphics.adLibPieces, ...clips, ...ografGraphics.adLibPieces], actions: [], } } diff --git a/packages/blueprints/src/base/showstyle/part-adapters/remote.ts b/packages/blueprints/src/base/showstyle/part-adapters/remote.ts index 4a223eec1..84b284fa0 100644 --- a/packages/blueprints/src/base/showstyle/part-adapters/remote.ts +++ b/packages/blueprints/src/base/showstyle/part-adapters/remote.ts @@ -11,6 +11,7 @@ import { createVisionMixerObjects } from '../helpers/visionMixer.js' import { getOutputLayerForSourceLayer, SourceLayer } from '../applyconfig/layers.js' import { ObjectType } from '../../../common/definitions/objects.js' import { parseConfig } from '../helpers/config.js' +import { parseOGrafGraphicsFromObjects } from '../helpers/ograf-graphics.js' export function generateRemotePart(context: PartContext, part: PartProps): BlueprintResultPart { const config = parseConfig(context).studio @@ -47,6 +48,8 @@ export function generateRemotePart(context: PartContext, part: PartProps): BlueprintResultPart { const config = parseConfig(context).studio @@ -84,6 +85,8 @@ export function generateVOPart(context: PartContext, part: PartProps): const graphics = parseGraphicsFromObjects(config, part.objects) if (graphics.pieces) pieces.push(...graphics.pieces) + const ografGraphics = parseOGrafGraphicsFromObjects(config, part.objects) + if (ografGraphics.pieces) pieces.push(...ografGraphics.pieces) return { part: { @@ -93,7 +96,7 @@ export function generateVOPart(context: PartContext, part: PartProps): expectedDuration: part.payload.duration, }, pieces, - adLibPieces: [...graphics.adLibPieces], + adLibPieces: [...graphics.adLibPieces, ...ografGraphics.adLibPieces], actions: [], } } diff --git a/packages/blueprints/src/base/showstyle/part-adapters/vt.ts b/packages/blueprints/src/base/showstyle/part-adapters/vt.ts index f669bdb0a..fda83c6fb 100644 --- a/packages/blueprints/src/base/showstyle/part-adapters/vt.ts +++ b/packages/blueprints/src/base/showstyle/part-adapters/vt.ts @@ -18,6 +18,7 @@ import { createVisionMixerObjects } from '../helpers/visionMixer.js' import { getOutputLayerForSourceLayer, SourceLayer } from '../applyconfig/layers.js' import { TimelineBlueprintExt } from '../../studio/customTypes.js' import { parseConfig } from '../helpers/config.js' +import { parseOGrafGraphicsFromObjects } from '../helpers/ograf-graphics.js' export function generateVTPart(context: PartContext, part: PartProps): BlueprintResultPart { const config = parseConfig(context).studio @@ -94,6 +95,8 @@ export function generateVTPart(context: PartContext, part: PartProps): const graphics = parseGraphicsFromObjects(config, part.objects) if (graphics.pieces) pieces.push(...graphics.pieces) + const ografGraphics = parseOGrafGraphicsFromObjects(config, part.objects) + if (ografGraphics.pieces) pieces.push(...ografGraphics.pieces) return { part: { @@ -104,7 +107,7 @@ export function generateVTPart(context: PartContext, part: PartProps): autoNext: true, }, pieces, - adLibPieces: [...graphics.adLibPieces], + adLibPieces: [...graphics.adLibPieces, ...ografGraphics.adLibPieces], actions: [], } } diff --git a/packages/blueprints/src/base/showstyle/rundown/globalActions.ts b/packages/blueprints/src/base/showstyle/rundown/globalActions.ts index 0caf847f8..417b5cf31 100644 --- a/packages/blueprints/src/base/showstyle/rundown/globalActions.ts +++ b/packages/blueprints/src/base/showstyle/rundown/globalActions.ts @@ -35,6 +35,17 @@ export function getGlobalActions( }, externalId: ingestRundown.externalId, }), + literal({ + actionId: ActionId.OGrafClear, + userData: {}, + userDataManifest: {}, + display: { + label: t('Clear Graphics'), + sourceLayerId: SourceLayer.OGrafOverlay1, + outputLayerId: getOutputLayerForSourceLayer(SourceLayer.OGrafOverlay1), + }, + externalId: ingestRundown.externalId, + }), exampleGraphicNextStepAdlibAction(ingestRundown), ] } diff --git a/packages/blueprints/src/base/showstyle/sofie-editor-parsers/index.ts b/packages/blueprints/src/base/showstyle/sofie-editor-parsers/index.ts index d780bc476..3e1b87368 100644 --- a/packages/blueprints/src/base/showstyle/sofie-editor-parsers/index.ts +++ b/packages/blueprints/src/base/showstyle/sofie-editor-parsers/index.ts @@ -52,6 +52,9 @@ export function convertIngestData(context: IRundownUserContext, ingestSegment: S } } else if ((piece.objectType as ObjectType) === ObjectType.Video) { piece.clipName = piece.attributes.fileName as string + } else if (piece.objectType.startsWith('ograf-')) { + piece.objectType = ObjectType.OGrafGraphic + piece.clipName = piece.name ?? 'N/A' } piece.duration = piece.duration * 1000 diff --git a/packages/blueprints/src/base/studio/applyConfig/index.ts b/packages/blueprints/src/base/studio/applyConfig/index.ts index e3d0332ab..9fe228ebb 100644 --- a/packages/blueprints/src/base/studio/applyConfig/index.ts +++ b/packages/blueprints/src/base/studio/applyConfig/index.ts @@ -80,6 +80,15 @@ function generatePlayoutDevices(config: BlueprintConfig): BlueprintResultApplySt }, }), }, + ograf0: { + parentConfigId: 'playoutgateway', + options: literal({ + type: TSR.DeviceType.OGRAF, + options: { + url: 'http://localhost:8080/ograf/v1', + }, + }), + }, } if (config.studio.visionMixer.type === VisionMixerDevice.Atem) { diff --git a/packages/blueprints/src/base/studio/applyConfig/mappings/mappings-defaults.ts b/packages/blueprints/src/base/studio/applyConfig/mappings/mappings-defaults.ts index 3494d5287..b8c769cfd 100644 --- a/packages/blueprints/src/base/studio/applyConfig/mappings/mappings-defaults.ts +++ b/packages/blueprints/src/base/studio/applyConfig/mappings/mappings-defaults.ts @@ -3,6 +3,7 @@ import { literal } from '../../../../common/util.js' import { AudioSourceType, SourceType, StudioConfig } from '../../helpers/config.js' import { AsbtractLayers, AtemLayers, CasparCGLayers, SisyfosLayers, VMixLayers } from './layers.js' import { VmixInputConfig, SiyfosSourceConfig } from '../../../../$schemas/generated/main-studio-config.js' +import { OGrafLayers } from '../../layers.js' export default literal({ [AsbtractLayers.CoreAbstract]: { @@ -12,6 +13,50 @@ export default literal({ options: {}, }, + [OGrafLayers.OGrafFullScreen]: literal>({ + device: TSR.DeviceType.OGRAF, + deviceId: 'ograf0', + lookahead: LookaheadMode.NONE, + + options: { + mappingType: TSR.MappingOgrafType.RenderTarget, + rendererId: 'renderer-1', + renderTarget: '{"layerId": "layer-0"}', + }, + }), + [OGrafLayers.OGrafOverlay1]: literal>({ + device: TSR.DeviceType.OGRAF, + deviceId: 'ograf0', + lookahead: LookaheadMode.NONE, + + options: { + mappingType: TSR.MappingOgrafType.RenderTarget, + rendererId: 'renderer-1', + renderTarget: '{"layerId": "layer-1"}', + }, + }), + [OGrafLayers.OGrafOverlay2]: literal>({ + device: TSR.DeviceType.OGRAF, + deviceId: 'ograf0', + lookahead: LookaheadMode.NONE, + + options: { + mappingType: TSR.MappingOgrafType.RenderTarget, + rendererId: 'renderer-1', + renderTarget: '{"layerId": "layer-2"}', + }, + }), + [OGrafLayers.OGrafOverlay3]: literal>({ + device: TSR.DeviceType.OGRAF, + deviceId: 'ograf0', + lookahead: LookaheadMode.NONE, + + options: { + mappingType: TSR.MappingOgrafType.RenderTarget, + rendererId: 'renderer-1', + renderTarget: '{"layerId": "layer-3"}', + }, + }), [CasparCGLayers.CasparCGClipPlayer1]: literal>({ device: TSR.DeviceType.CASPARCG, deviceId: 'casparcg0', diff --git a/packages/blueprints/src/base/studio/layers.ts b/packages/blueprints/src/base/studio/layers.ts index f75a87b37..fbcb8a78c 100644 --- a/packages/blueprints/src/base/studio/layers.ts +++ b/packages/blueprints/src/base/studio/layers.ts @@ -12,7 +12,12 @@ export enum VMixLayers { VMixOverlayGraphics = 'vmix_overlay_graphics', VMixDVEMultiView = 'vmix_dve_multiview', } - +export enum OGrafLayers { + OGrafFullScreen = 'ograf_full_screen', + OGrafOverlay1 = 'ograf_overlay_1', + OGrafOverlay2 = 'ograf_overlay_2', + OGrafOverlay3 = 'ograf_overlay_3', +} export enum CasparCGLayers { CasparCGClipPlayer1 = 'casparcg_clip_player1', CasparCGClipPlayer2 = 'casparcg_clip_player2', diff --git a/packages/blueprints/src/common/definitions/objects.ts b/packages/blueprints/src/common/definitions/objects.ts index a36b4f96f..c669f6ccd 100644 --- a/packages/blueprints/src/common/definitions/objects.ts +++ b/packages/blueprints/src/common/definitions/objects.ts @@ -3,6 +3,7 @@ import { SpreadsheetIngestPiece } from '../../code-copy/spreadsheet-gateway/inde export type SomeObject = | CameraObject | VideoObject + | OGrafGraphicObject | GraphicObject | SplitObject | OverlayObject @@ -21,6 +22,7 @@ export type SomeAdlibPiece = VideoObject | GraphicObject export enum ObjectType { Camera = 'camera', Video = 'video', + OGrafGraphic = 'ograf-graphic', Graphic = 'graphic', SteppedGraphic = 'stepped-graphic', Split = 'split', @@ -50,9 +52,18 @@ export interface VideoObject extends BaseObject { adlibVariant?: string } export interface GraphicObjectBase extends BaseObject { - objectType: ObjectType.Graphic | ObjectType.SteppedGraphic + objectType: ObjectType.OGrafGraphic | ObjectType.Graphic | ObjectType.SteppedGraphic adlibVariant?: string } +export interface OGrafGraphicObject extends GraphicObjectBase { + objectType: ObjectType.OGrafGraphic + attributes: OGrafGraphicObjectAttributes +} +export type OGrafGraphicObjectAttributes = { + 'ograf-id': string + 'ograf-data': any + type: string | 'full-screen' | 'overlay1' | 'overlay2' | 'overlay3' +} export interface GraphicObject extends GraphicObjectBase { objectType: ObjectType.Graphic attributes: GraphicObjectAttributes