diff --git a/package.json b/package.json index 556bc79c2..fa692afbe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tv2-sofie-blueprints-inews", - "version": "1.7.4", + "version": "1.7.5", "repository": "https://github.com/olzzon/tv2-sofie-blueprints-inews", "license": "MIT", "private": true, diff --git a/src/__mocks__/context.ts b/src/__mocks__/context.ts index 0e31148fd..1473f5ca3 100644 --- a/src/__mocks__/context.ts +++ b/src/__mocks__/context.ts @@ -4,7 +4,6 @@ import * as _ from 'underscore' import { BlueprintMappings, ConfigItemValue, - IActionExecutionContext, IBlueprintConfig, IBlueprintMutatablePart, IBlueprintPart, @@ -30,7 +29,7 @@ import { PlaylistTimingType, Time } from '@tv2media/blueprints-integration' -import { literal } from 'tv2-common' +import { ITV2ActionExecutionContext, PieceMetaData } from 'tv2-common' import { NoteType } from 'tv2-constants' import { defaultShowStyleConfig, defaultStudioConfig } from '../tv2_afvd_showstyle/__tests__/configs' import { parseConfig as parseShowStyleConfigAFVD } from '../tv2_afvd_showstyle/helpers/config' @@ -82,7 +81,6 @@ export class CommonContext implements ICommonContext { id = getHash(this.contextName + '_' + str.toString()) this.hashed[id] = str return id - // return Random.id() } public unhashId(hash: string): string { return this.hashed[hash] || hash @@ -327,7 +325,7 @@ export class SyncIngestUpdateToPartInstanceContext extends RundownUserContext mutatedPiece?: Omit, 'lifespan'> ): IBlueprintPieceInstance { this.syncedPieceInstances.push(pieceInstanceId) - return literal({ + return { _id: pieceInstanceId, piece: { _id: '', @@ -343,24 +341,24 @@ export class SyncIngestUpdateToPartInstanceContext extends RundownUserContext content: mutatedPiece?.content ?? { timelineObjects: [] } }, partInstanceId: '' - }) + } } public insertPieceInstance(piece: IBlueprintPiece): IBlueprintPieceInstance { - return literal({ + return { _id: '', piece: { _id: '', ...piece }, partInstanceId: '' - }) + } } public updatePieceInstance( pieceInstanceId: string, piece: Partial> ): IBlueprintPieceInstance { this.updatedPieceInstances.push(pieceInstanceId) - return literal({ + return { _id: pieceInstanceId, piece: { _id: '', @@ -376,14 +374,14 @@ export class SyncIngestUpdateToPartInstanceContext extends RundownUserContext content: piece.content ?? { timelineObjects: [] } }, partInstanceId: '' - }) + } } public removePieceInstances(...pieceInstanceIds: string[]): string[] { this.removedPieceInstances.push(...pieceInstanceIds) return pieceInstanceIds } public updatePartInstance(props: Partial>): IBlueprintPartInstance { - this.updatedPartInstance = literal({ + this.updatedPartInstance = { _id: '', segmentId: '', part: { @@ -394,7 +392,7 @@ export class SyncIngestUpdateToPartInstanceContext extends RundownUserContext ...props }, rehearsal: false - }) + } return this.updatedPartInstance } @@ -404,13 +402,14 @@ export class SyncIngestUpdateToPartInstanceContext extends RundownUserContext } // tslint:disable-next-line: max-classes-per-file -export class ActionExecutionContext extends ShowStyleUserContext implements IActionExecutionContext { +export class ActionExecutionContext extends ShowStyleUserContext implements ITV2ActionExecutionContext { public currentPart: IBlueprintPartInstance - public currentPieceInstances: IBlueprintPieceInstance[] + public currentPieceInstances: Array> public nextPart: IBlueprintPartInstance | undefined - public nextPieceInstances: IBlueprintPieceInstance[] | undefined + public nextPieceInstances: Array> | undefined public takeAfterExecute: boolean = false + public isTV2Context: true = true constructor( contextName: string, @@ -421,9 +420,9 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct segmentId: string, partId: string, currentPart: IBlueprintPartInstance, - currentPieceInstances: IBlueprintPieceInstance[], + currentPieceInstances: Array>, nextPart?: IBlueprintPartInstance, - nextPieceInstances?: IBlueprintPieceInstance[] + nextPieceInstances?: Array> ) { super(contextName, mappingsDefaults, parseStudioConfig, parseShowStyleConfig, rundownId, segmentId, partId) @@ -446,7 +445,7 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct return this.nextPart } /** Get the PieceInstances for a modifiable PartInstance */ - public async getPieceInstances(part: 'current' | 'next'): Promise { + public async getPieceInstances(part: 'current' | 'next'): Promise>> { if (part === 'current') { return this.currentPieceInstances } @@ -454,7 +453,9 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct return this.nextPieceInstances || [] } /** Get the resolved PieceInstances for a modifiable PartInstance */ - public async getResolvedPieceInstances(_part: 'current' | 'next'): Promise { + public async getResolvedPieceInstances( + _part: 'current' | 'next' + ): Promise>> { return [] } /** Get the last active piece on given layer */ @@ -465,7 +466,7 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct originalOnly?: boolean pieceMetaDataFilter?: any } - ): Promise { + ): Promise | undefined> { return undefined } public async findLastScriptedPieceOnLayer( @@ -474,11 +475,11 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct excludeCurrentPart?: boolean pieceMetaDataFilter?: any } - ): Promise { + ): Promise | undefined> { return undefined } public async getPartInstanceForPreviousPiece(_piece: IBlueprintPieceInstance): Promise { - return literal({ + return { _id: '', segmentId: '', part: { @@ -488,15 +489,18 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct title: '' }, rehearsal: false - }) + } } public async getPartForPreviousPiece(_piece: { _id: string }): Promise { return undefined } /** Creative actions */ /** Insert a piece. Returns id of new PieceInstance. Any timelineObjects will have their ids changed, so are not safe to reference from another piece */ - public async insertPiece(part: 'current' | 'next', piece: IBlueprintPiece): Promise { - const pieceInstance: IBlueprintPieceInstance = { + public async insertPiece( + part: 'current' | 'next', + piece: IBlueprintPiece + ): Promise> { + const pieceInstance: IBlueprintPieceInstance = { _id: '', piece: { _id: '', @@ -517,19 +521,22 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct public async updatePieceInstance( _pieceInstanceId: string, piece: Partial> - ): Promise { + ): Promise> { return { _id: '', piece: { _id: '', - ...(piece as IBlueprintPiece) + ...(piece as IBlueprintPiece) }, partInstanceId: '' } } /** Insert a queued part to follow the current part */ - public async queuePart(part: IBlueprintPart, pieces: IBlueprintPiece[]): Promise { - const instance = literal({ + public async queuePart( + part: IBlueprintPart, + pieces: Array> + ): Promise { + const instance: IBlueprintPartInstance = { _id: '', segmentId: this.notesSegmentId || '', part: { @@ -538,10 +545,10 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct segmentId: this.notesSegmentId || '' }, rehearsal: false - }) + } this.nextPart = instance - this.nextPieceInstances = pieces.map(p => ({ + this.nextPieceInstances = pieces.map>(p => ({ _id: (Date.now() * Math.random()).toString(), piece: { _id: '', diff --git a/src/inews-mixins/playlist.ts b/src/inews-mixins/playlist.ts index 0742f164f..9da91bec0 100644 --- a/src/inews-mixins/playlist.ts +++ b/src/inews-mixins/playlist.ts @@ -93,13 +93,13 @@ function getRundownPlaylistInfoINewsPlaylist( resultPlaylist: BlueprintResultRundownPlaylist ): BlueprintResultRundownPlaylist { const result: BlueprintResultOrderedRundowns = {} - return literal({ + return { ...resultPlaylist, order: rundowns.reduce((prev, curr) => { prev[curr.externalId] = (curr.metaData as RundownMetaData).rank return prev }, result) - }) + } } type GetRundownMixin = ( @@ -152,15 +152,15 @@ export function GetRundownPlaylistInfoWithMixins( expectedStart: lastRundownTiming.expectedStart } } - let result = - (getRundownPlaylistInfo ? getRundownPlaylistInfo(context, rundowns, '') : undefined) ?? - literal({ - playlist: literal({ - name: (rundowns[0] ?? { name: '' }).name, - timing - }), - order: null - }) + let result: BlueprintResultRundownPlaylist = (getRundownPlaylistInfo + ? getRundownPlaylistInfo(context, rundowns, '') + : undefined) ?? { + playlist: literal({ + name: (rundowns[0] ?? { name: '' }).name, + timing + }), + order: null + } for (const mixin of mixins) { result = mixin(context, rundowns, result) diff --git a/src/tv2-common/__tests__/onTimelineGenerate.spec.ts b/src/tv2-common/__tests__/onTimelineGenerate.spec.ts index 9c3b39682..015636d75 100644 --- a/src/tv2-common/__tests__/onTimelineGenerate.spec.ts +++ b/src/tv2-common/__tests__/onTimelineGenerate.spec.ts @@ -5,7 +5,6 @@ import { PieceMetaData, SisyfosPersistMetaData } from '../onTimelineGenerate' -import { literal } from '../util' const LAYER_THAT_WANTS_TO_BE_PERSISTED = 'layerThatWantsToBePersisted' const LAYERS_THAT_WANTS_TO_BE_PERSISTED_ARRAY: SisyfosPersistMetaData['sisyfosLayers'] = [ @@ -16,7 +15,7 @@ const LAYERS_THAT_WANTS_TO_BE_PERSISTED_ARRAY: SisyfosPersistMetaData['sisyfosLa describe('onTimelineGenerate', () => { describe('createSisyfosPersistedLevelsTimelineObject', () => { it('has one layer to persist, piece accept persist - timelineObject with layer is added', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('currentPiece', 10, undefined, true, true) ] @@ -29,7 +28,7 @@ describe('onTimelineGenerate', () => { }) it('has layer to persist, timelineObject with correct Sisyfos information is added', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('currentPiece', 10, undefined, true, true) ] @@ -42,7 +41,7 @@ describe('onTimelineGenerate', () => { }) it('should persist non-VO layers with isPgm 1', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('currentPiece', 10, undefined, true, true) ] @@ -51,7 +50,7 @@ describe('onTimelineGenerate', () => { }) it('should persist only current piece layer when piece wants to persist but dont accept', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('previousPiece', 0, 10, true, true), createPieceInstance('currentPiece', 10, undefined, true, false) ] @@ -62,7 +61,7 @@ describe('onTimelineGenerate', () => { }) it('should not persist anything when current piece dont accept and dont want to persist', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('previousPiece', 0, 10, true, true), createPieceInstance('currentPiece', 10, undefined, false, false) ] @@ -73,7 +72,7 @@ describe('onTimelineGenerate', () => { }) it('should persist when previous piece does not accept persist, but current does accept', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('previousPiece', 0, 10, true, false), createPieceInstance('currentPiece', 10, undefined, false, true) ] @@ -84,7 +83,9 @@ describe('onTimelineGenerate', () => { }) it('should persist when current piece accepts persist and duration is not undefined', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [createPieceInstance('currentPiece', 0, 5, false, true)] + const resolvedPieces: Array> = [ + createPieceInstance('currentPiece', 0, 5, false, true) + ] const result = createSisyfosPersistedLevelsTimelineObject(resolvedPieces, LAYERS_THAT_WANTS_TO_BE_PERSISTED_ARRAY) @@ -100,7 +101,9 @@ describe('onTimelineGenerate', () => { secondLayerThatWantToBePersisted, thirdLayerThatWantToBePersisted ] - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [createPieceInstance('currentPiece', 0, 5, true, true)] + const resolvedPieces: Array> = [ + createPieceInstance('currentPiece', 0, 5, true, true) + ] const result = createSisyfosPersistedLevelsTimelineObject(resolvedPieces, layersThatWantToBePersisted) @@ -116,7 +119,7 @@ describe('onTimelineGenerate', () => { }) it('cuts to executeAction that dont accept persist, dont persist layers', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('previousPieceNotExecuteAction', 0, 10, true, true), createExecuteActionPieceInstance('currentPieceIsExecuteAction', 10, undefined, false, false) ] @@ -127,7 +130,7 @@ describe('onTimelineGenerate', () => { }) it('cuts to executeAction that accept persist from piece that accept, add persist timelineObject containing all layers that want to be persisted plus previous piece layers', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('previousPieceNotExecuteAction', 0, 10, true, true), createExecuteActionPieceInstance('currentPieceIsExecuteAction', 10, undefined, false, true) ] @@ -141,7 +144,7 @@ describe('onTimelineGenerate', () => { }) it('cuts to executionAction that accept from piece that dont accept, add persist timelineObject that only contain previous piece layers', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('previousPieceNotExecuteAction', 0, 10, true, false), createExecuteActionPieceInstance('currentPieceIsExecuteAction', 10, undefined, false, true) ] @@ -153,7 +156,7 @@ describe('onTimelineGenerate', () => { }) it('cuts to executeAction that accept persist from piece that dont want to persist and dont accept persist, dont persist any layers', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('previousPieceNotExecuteAction', 0, 10, false, false), createExecuteActionPieceInstance('currentPieceIsExecuteAction', 10, undefined, false, true) ] @@ -164,7 +167,7 @@ describe('onTimelineGenerate', () => { }) it('cuts to executeAction that accept persist from piece that dont want to persist and that accept persist, persist previous layers', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('previousPieceNotExecuteAction', 0, 10, false, true), createExecuteActionPieceInstance('currentPieceIsExecuteAction', 10, undefined, false, true) ] @@ -178,7 +181,7 @@ describe('onTimelineGenerate', () => { }) it('cuts from executeAction that dont accept to piece that accepts, dont persist', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createExecuteActionPieceInstance('previousPieceIsExecuteAction', 0, 10, false, false), createPieceInstance('currentPieceNotExecuteAction', 10, undefined, false, true) ] @@ -189,7 +192,7 @@ describe('onTimelineGenerate', () => { }) it('cuts from executeAction that dont accept to piece that dont accepts, dont persist layers', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createExecuteActionPieceInstance('previousPieceIsExecuteAction', 0, 10, false, false), createPieceInstance('currentPieceNotExecuteAction', 10, undefined, false, false) ] @@ -200,7 +203,7 @@ describe('onTimelineGenerate', () => { }) it('cuts from executeAction that accept to piece that dont accepts, dont persist layers', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createExecuteActionPieceInstance('previousPieceIsExecuteAction', 0, 10, false, true), createPieceInstance('currentPieceNotExecuteAction', 10, undefined, false, false) ] @@ -211,7 +214,7 @@ describe('onTimelineGenerate', () => { }) it('cuts from executeAction that accept to piece that accepts, add persist timelineObject with previous layer before executeAction + new layer', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('firstPiece', 0, 5, true, true), createExecuteActionPieceInstance('previousPieceIsExecuteAction', 5, 5, false, true, { acceptPersistAudio: true, @@ -226,7 +229,7 @@ describe('onTimelineGenerate', () => { }) it('cuts from piece that wants to persist to executeAction that do not accept to piece that accepts, do not persist', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('firstPiece', 0, 5, true, true), createExecuteActionPieceInstance('previousPieceIsExecuteAction', 5, 5, false, true, { acceptPersistAudio: false, @@ -241,7 +244,7 @@ describe('onTimelineGenerate', () => { }) it('cuts from piece that wants to persist to executeAction that accepts to another executeAction that accepts, persist layer from first piece', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('firstPiece', 0, 5, true, true), createExecuteActionPieceInstance('executeAction', 5, undefined, false, true, { acceptPersistAudio: true, @@ -260,7 +263,7 @@ describe('onTimelineGenerate', () => { }) it('cuts from piece that wants to persist to executeAction that do not accept to another executeAction that accepts, dont persist any layers', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('firstPiece', 0, 5, true, true), createExecuteActionPieceInstance('executeAction', 5, undefined, false, true, { acceptPersistAudio: true, @@ -278,7 +281,7 @@ describe('onTimelineGenerate', () => { }) it('should not contain any duplicate layers to persist', () => { - const resolvedPieces: IBlueprintResolvedPieceInstance[] = [ + const resolvedPieces: Array> = [ createPieceInstance('piece', 0, 5, true, true), createPieceInstance('piece', 5, undefined, true, true) ] @@ -296,21 +299,21 @@ function createPieceInstance( duration: number | undefined, wantToPersistAudio: boolean, acceptPersistAudio: boolean -): IBlueprintResolvedPieceInstance { +): IBlueprintResolvedPieceInstance { return { resolvedStart: start, resolvedDuration: duration, piece: { name, - metaData: literal({ + metaData: { sisyfosPersistMetaData: { sisyfosLayers: [name], wantsToPersistAudio: wantToPersistAudio, acceptPersistAudio } - }) - } as IBlueprintPieceDB - } as IBlueprintResolvedPieceInstance + } + } as IBlueprintPieceDB + } as IBlueprintResolvedPieceInstance } function createExecuteActionPieceInstance( @@ -320,7 +323,7 @@ function createExecuteActionPieceInstance( wantToPersistAudio: boolean, acceptPersistAudio: boolean, previousMetaData?: SisyfosPersistMetaData -): IBlueprintResolvedPieceInstance { +): IBlueprintResolvedPieceInstance { return { resolvedStart: start, resolvedDuration: duration, @@ -332,8 +335,8 @@ function createExecuteActionPieceInstance( wantsToPersistAudio: wantToPersistAudio, acceptPersistAudio, previousPersistMetaDataForCurrentPiece: previousMetaData - } as SisyfosPersistMetaData + } } - } as IBlueprintPieceDB - } as IBlueprintResolvedPieceInstance + } as IBlueprintPieceDB + } as IBlueprintResolvedPieceInstance } diff --git a/src/tv2-common/actions/actionTypes.ts b/src/tv2-common/actions/actionTypes.ts index 9e1479dd7..0d0e3c282 100644 --- a/src/tv2-common/actions/actionTypes.ts +++ b/src/tv2-common/actions/actionTypes.ts @@ -2,8 +2,6 @@ import { AdlibActionType } from 'tv2-constants' import { DVEConfigInput } from '../helpers' import { CueDefinitionDVE, - CueDefinitionGraphic, - GraphicInternal, PartDefinition, SourceDefinition, SourceDefinitionKam, @@ -137,11 +135,6 @@ export interface ActionFadeDownPersistedAudioLevels extends ActionBase { type: AdlibActionType.FADE_DOWN_PERSISTED_AUDIO_LEVELS } -export interface ActionPlayGraphics extends ActionBase { - type: AdlibActionType.PLAY_GRAPHICS - graphic: CueDefinitionGraphic -} - export type TV2AdlibAction = | ActionSelectServerClip | ActionSelectDVE @@ -159,4 +152,3 @@ export type TV2AdlibAction = | ActionRecallLastLive | ActionRecallLastDVE | ActionFadeDownPersistedAudioLevels - | ActionPlayGraphics diff --git a/src/tv2-common/actions/context.ts b/src/tv2-common/actions/context.ts index 21e2da47f..e0a8ad5b7 100644 --- a/src/tv2-common/actions/context.ts +++ b/src/tv2-common/actions/context.ts @@ -11,11 +11,42 @@ import { PackageInfo, Time } from '@tv2media/blueprints-integration' -import { literal, PartMetaData } from 'tv2-common' +import { literal, PartMetaData, PieceMetaData } from 'tv2-common' export interface ITV2ActionExecutionContext extends IActionExecutionContext { /** To prompt type errors for wrong context type */ isTV2Context: true + + getPieceInstances(part: 'current' | 'next'): Promise>> + getResolvedPieceInstances(part: 'current' | 'next'): Promise>> + + findLastPieceOnLayer( + sourceLayerId: string | string[], + options?: { + excludeCurrentPart?: boolean + originalOnly?: boolean + pieceMetaDataFilter?: any + } + ): Promise | undefined> + findLastScriptedPieceOnLayer( + sourceLayerId: string | string[], + options?: { + excludeCurrentPart?: boolean + pieceMetaDataFilter?: any + } + ): Promise | undefined> + getPartInstanceForPreviousPiece(piece: IBlueprintPieceInstance): Promise + getPartForPreviousPiece(piece: IBlueprintPieceDB): Promise + insertPiece( + part: 'current' | 'next', + piece: IBlueprintPiece + ): Promise> + updatePieceInstance( + pieceInstanceId: string, + piece: Partial> + ): Promise> + queuePart(part: IBlueprintPart, pieces: Array>): Promise + updatePartInstance(part: 'current' | 'next', props: Partial): Promise } class TV2ActionExecutionContext implements ITV2ActionExecutionContext { @@ -35,42 +66,48 @@ class TV2ActionExecutionContext implements ITV2ActionExecutionContext { return this.coreContext.getPartInstance(part) } - public async getPieceInstances(part: 'current' | 'next'): Promise>> { - return this.coreContext.getPieceInstances(part) + public async getPieceInstances(part: 'current' | 'next'): Promise>> { + return this.coreContext.getPieceInstances(part) as Promise>> } public async getResolvedPieceInstances( part: 'current' | 'next' - ): Promise>> { - return this.coreContext.getResolvedPieceInstances(part) + ): Promise>> { + return this.coreContext.getResolvedPieceInstances(part) as Promise< + Array> + > } public async findLastPieceOnLayer( sourceLayerId: string | string[], options?: { - excludeCurrentPart?: boolean | undefined - originalOnly?: boolean | undefined + excludeCurrentPart?: boolean + originalOnly?: boolean pieceMetaDataFilter?: any } - ): Promise | undefined> { - return this.coreContext.findLastPieceOnLayer(sourceLayerId, options) + ): Promise | undefined> { + return this.coreContext.findLastPieceOnLayer(sourceLayerId, options) as Promise< + IBlueprintPieceInstance | undefined + > } public async findLastScriptedPieceOnLayer( sourceLayerId: string | string[], - options?: { excludeCurrentPart?: boolean | undefined; pieceMetaDataFilter?: any } - ): Promise | undefined> { - return this.coreContext.findLastScriptedPieceOnLayer(sourceLayerId, options) + options?: { excludeCurrentPart?: boolean; pieceMetaDataFilter?: any } + ): Promise | undefined> { + return this.coreContext.findLastScriptedPieceOnLayer(sourceLayerId, options) as Promise< + IBlueprintPiece | undefined + > } public async getPartInstanceForPreviousPiece( - piece: IBlueprintPieceInstance + piece: IBlueprintPieceInstance ): Promise> { return this.coreContext.getPartInstanceForPreviousPiece(piece) } public async getPartForPreviousPiece( - piece: IBlueprintPieceDB + piece: IBlueprintPieceDB ): Promise | undefined> { return this.coreContext.getPartForPreviousPiece(piece) } @@ -157,7 +194,10 @@ class TV2ActionExecutionContext implements ITV2ActionExecutionContext { return this.coreContext.moveNextPart(partDelta, segmentDelta) } - public async queuePart(rawPart: IBlueprintPart, rawPieces: IBlueprintPiece[]): Promise { + public async queuePart( + rawPart: IBlueprintPart, + rawPieces: Array> + ): Promise { this.modifiedParts.add('next') return this.coreContext.queuePart(rawPart, rawPieces) @@ -169,9 +209,12 @@ class TV2ActionExecutionContext implements ITV2ActionExecutionContext { return this.coreContext.removePieceInstances(part, pieceInstanceIds) } - public async insertPiece(part: 'current' | 'next', piece: IBlueprintPiece): Promise { + public async insertPiece( + part: 'current' | 'next', + piece: IBlueprintPiece + ): Promise> { this.modifiedParts.add(part) - return this.coreContext.insertPiece(part, piece) + return this.coreContext.insertPiece(part, piece) as Promise> } public async updatePartInstance( @@ -184,8 +227,8 @@ class TV2ActionExecutionContext implements ITV2ActionExecutionContext { public async updatePieceInstance( pieceInstanceId: string, - piece: Partial - ): Promise { + piece: Partial> + ): Promise> { const currentPieceInstances = await this.coreContext.getPieceInstances('current') if (currentPieceInstances.map(p => p._id).includes(pieceInstanceId)) { this.modifiedParts.add('current') @@ -197,7 +240,9 @@ class TV2ActionExecutionContext implements ITV2ActionExecutionContext { } // Regardless of above, let core handle errors - return this.coreContext.updatePieceInstance(pieceInstanceId, piece) + return this.coreContext.updatePieceInstance(pieceInstanceId, piece) as Promise< + IBlueprintPieceInstance + > } /** diff --git a/src/tv2-common/actions/executeAction.ts b/src/tv2-common/actions/executeAction.ts index 3c956756b..1b2420ca5 100644 --- a/src/tv2-common/actions/executeAction.ts +++ b/src/tv2-common/actions/executeAction.ts @@ -10,7 +10,6 @@ import { IBlueprintPieceDB, IBlueprintPieceGeneric, IBlueprintPieceInstance, - IBlueprintResolvedPieceInstance, IShowStyleUserContext, PieceLifespan, SplitsContent, @@ -26,7 +25,6 @@ import { ActionCutSourceToBox, ActionCutToCamera, ActionCutToRemote, - ActionPlayGraphics, ActionSelectDVE, ActionSelectDVELayout, ActionSelectFullGrafik, @@ -47,7 +45,6 @@ import { GetDVETemplate, GetFullGrafikTemplateName, GraphicPilot, - IsTargetingOVL, ITV2ActionExecutionContext, literal, MakeContentDVE2, @@ -81,7 +78,6 @@ import { PilotGraphicGenerator, ServerSelectMode } from '../helpers' -import { InternalGraphic } from '../helpers/graphics/InternalGraphic' import { GetJinglePartPropertiesFromTableValue } from '../jinglePartProperties' import { CreateEffektForPartBase, CreateEffektForPartInner, CreateMixTransitionBlueprintPieceForPart } from '../parts' import { @@ -105,7 +101,6 @@ import { const STOPPABLE_GRAPHICS_LAYERS = [ SharedSourceLayers.PgmGraphicsIdent, - SharedSourceLayers.PgmGraphicsIdentPersistent, SharedSourceLayers.PgmGraphicsTop, SharedSourceLayers.PgmGraphicsLower, SharedSourceLayers.PgmGraphicsHeadline, @@ -280,9 +275,6 @@ export async function executeAction< case AdlibActionType.FADE_DOWN_PERSISTED_AUDIO_LEVELS: await executeActionFadeDownPersistedAudioLevels(context, settings) break - case AdlibActionType.PLAY_GRAPHICS: - await executeActionPlayGraphics(context, settings, actionId, userData as ActionPlayGraphics) - break default: assertUnreachable(actionId) break @@ -378,7 +370,7 @@ async function getExistingTransition< return } -function sanitizePieceId(piece: IBlueprintPieceDB): IBlueprintPiece { +function sanitizePieceId(piece: IBlueprintPieceDB): IBlueprintPiece { return _.omit(piece, ['_id', 'partId', 'infiniteId', 'playoutDuration']) } @@ -386,7 +378,7 @@ export async function getPiecesToPreserve( context: ITV2ActionExecutionContext, adlibLayers: string[], ignoreLayers: string[] -): Promise { +): Promise>> { const currentPartSegmentId = await context.getPartInstance('current').then(partInstance => partInstance?.segmentId) const nextPartSegmentId = await context.getPartInstance('next').then(partInstance => partInstance?.segmentId) @@ -402,9 +394,9 @@ export async function getPiecesToPreserve( return pieceInstances .filter(p => adlibLayers.includes(p.piece.sourceLayerId) && !ignoreLayers.includes(p.piece.sourceLayerId)) .filter(p => !p.infinite?.fromPreviousPart && !p.infinite?.fromPreviousPlayhead) - .map(p => p.piece) + .map>(p => p.piece) .map(p => sanitizePieceStart(p)) - .map(p => sanitizePieceId(p as IBlueprintPieceDB)) + .map(p => sanitizePieceId(p as IBlueprintPieceDB)) }) } @@ -486,8 +478,8 @@ async function executeActionSelectServerClip< let part = basePart.part.part - const grafikPieces: IBlueprintPiece[] = [] - const effektPieces: IBlueprintPiece[] = [] + const grafikPieces: Array> = [] + const effektPieces: Array> = [] part = { ...part, @@ -524,8 +516,8 @@ async function executeActionSelectServerClip< } await context.queuePart(part, [ - activeServerPiece, - serverDataStore, + activeServerPiece as IBlueprintPiece, // @todo: get rid of these casts + serverDataStore as IBlueprintPiece, ...grafikPieces, ...(settings.SelectedAdlibs ? await getPiecesToPreserve(context, settings.SelectedAdlibs.SELECTED_ADLIB_LAYERS, [ @@ -609,7 +601,7 @@ async function executeActionSelectDVE< start = start ? start : 0 const end = parsedCue.end ? CalculateTime(parsedCue.end) : undefined - const metaData = literal({ + const metaData: DVEPieceMetaData = { mediaPlayerSessions: dveContainsServer(parsedCue.sources) ? [externalId] : [], sources: parsedCue.sources, config: rawTemplate, @@ -617,9 +609,9 @@ async function executeActionSelectDVE< sisyfosLayers: [] }, userData - }) + } - let dvePiece = literal({ + let dvePiece: IBlueprintPiece = { externalId, name: `${parsedCue.template}`, enable: { @@ -640,7 +632,7 @@ async function executeActionSelectDVE< GetTagForDVENext(userData.segmentExternalId, parsedCue.template, parsedCue.sources), TallyTags.DVE_IS_LIVE ] - }) + } dvePiece = await cutServerToBox(context, settings, dvePiece) @@ -666,17 +658,17 @@ async function cutServerToBox< >( context: ITV2ActionExecutionContext, settings: ActionExecutionSettings, - newDvePiece: IBlueprintPiece, + newDvePiece: IBlueprintPiece, containedServerBefore?: boolean, modifiesCurrent?: boolean -): Promise { +): Promise> { // Check if DVE should continue server + copy server properties if (!newDvePiece.metaData) { return newDvePiece } - const meta = newDvePiece.metaData as DVEPieceMetaData + const meta = newDvePiece.metaData const containsServer = dveContainsServer(meta.sources) @@ -738,7 +730,7 @@ async function cutServerToBox< newDvePiece.content.timelineObjects[ssrcObjIndex] = ssrcObj newDvePiece.content.timelineObjects.push(EnableServer(existingCasparObj.metaData.mediaPlayerSession)) - ;(newDvePiece.metaData as any).mediaPlayerSessions = [existingCasparObj.metaData.mediaPlayerSession] + newDvePiece.metaData.mediaPlayerSessions = [existingCasparObj.metaData.mediaPlayerSession] if (!containedServerBefore) { startServerMetaData(context, meta, modifiesCurrent) @@ -792,11 +784,13 @@ async function executeActionSelectDVELayout< const nextPart = await context.getPartInstance('next') - const nextDVE = await context + const nextDVE = (await context .getPieceInstances('next') - .then(nextPieceInstances => nextPieceInstances.find(p => p.piece.sourceLayerId === settings.SourceLayers.DVE)) + .then(nextPieceInstances => nextPieceInstances.find(p => p.piece.sourceLayerId === settings.SourceLayers.DVE))) as + | IBlueprintPieceInstance + | undefined - const meta = nextDVE?.piece.metaData as DVEPieceMetaData + const meta = nextDVE?.piece.metaData if (!nextPart || !nextDVE || !meta || nextPart.segmentId !== (await context.getPartInstance('current'))?.segmentId) { const content = MakeContentDVE2(context, config, userData.config, {}, sources, settings.DVEGeneratorOptions) @@ -805,27 +799,27 @@ async function executeActionSelectDVELayout< return } - const newMetaData = literal({ + const newMetaData: DVEPieceMetaData = { sources, config: userData.config, sisyfosPersistMetaData: { sisyfosLayers: [] }, - userData: literal({ + userData: { type: AdlibActionType.SELECT_DVE, - config: literal({ + config: { type: CueType.DVE, template: userData.config.DVEName, sources, labels: [], iNewsCommand: `DVE=${userData.config.DVEName}` - }), + }, videoId: undefined, segmentExternalId: '' - }) - }) + } + } - let newDVEPiece = literal({ + let newDVEPiece: IBlueprintPiece = { externalId, enable: { start: 0 @@ -836,7 +830,7 @@ async function executeActionSelectDVELayout< outputLayerId: SharedOutputLayers.PGM, metaData: newMetaData, content: content.content - }) + } newDVEPiece = await cutServerToBox(context, settings, newDVEPiece) @@ -856,16 +850,16 @@ async function executeActionSelectDVELayout< ) } - const newMetaData2 = literal({ + const newMetaData2: DVEPieceMetaData = { ...meta, config: userData.config, sisyfosPersistMetaData: { sisyfosLayers: [] } - }) + } const pieceContent = MakeContentDVE2(context, config, userData.config, {}, meta.sources, settings.DVEGeneratorOptions) - let dvePiece: IBlueprintPiece = { + let dvePiece: IBlueprintPiece = { ...nextDVE.piece, content: pieceContent.content, metaData: newMetaData2, @@ -903,9 +897,9 @@ async function startNewDVELayout< context: ITV2ActionExecutionContext, config: ShowStyleConfig, settings: ActionExecutionSettings, - dvePiece: IBlueprintPiece, + dvePiece: IBlueprintPiece, pieceContent: WithTimeline, - meta: PieceMetaData & DVEPieceMetaData, + metaData: DVEPieceMetaData, templateName: string, _sources: CueDefinitionDVE['sources'], externalId: string, @@ -915,8 +909,8 @@ async function startNewDVELayout< ) { settings.postProcessPieceTimelineObjects(context, config, dvePiece, false) - const dveDataStore = settings.SelectedAdlibs.SourceLayer.DVE - ? literal({ + const dveDataStore: IBlueprintPiece | undefined = settings.SelectedAdlibs.SourceLayer.DVE + ? { externalId, name: templateName, enable: { @@ -925,7 +919,7 @@ async function startNewDVELayout< outputLayerId: settings.SelectedAdlibs.OutputLayer.SelectedAdLib, sourceLayerId: settings.SelectedAdlibs.SourceLayer.DVE, lifespan: PieceLifespan.OutOnSegmentEnd, - metaData: meta, + metaData, tags: [nextTag], content: { ...pieceContent, @@ -940,16 +934,16 @@ async function startNewDVELayout< ) .map(obj => ({ ...obj, priority: obj.priority ?? 1 / 2 })) } - }) + } : undefined if (replacePieceInstancesOrQueue === 'queue') { - const newPart = literal({ + const newPart: IBlueprintPart = { externalId, title: templateName, metaData: {}, expectedDuration: 0 - }) + } const currentPieceInstances = await context.getPieceInstances('current') // If a DVE is not on air, but a layout is selected, stop the selected layout and replace with the new one. @@ -957,7 +951,7 @@ async function startNewDVELayout< const dataPiece = settings.SelectedAdlibs && - currentPieceInstances.find(p => p.piece.sourceLayerId === settings.SelectedAdlibs!.SourceLayer.DVE) + currentPieceInstances.find(p => p.piece.sourceLayerId === settings.SelectedAdlibs.SourceLayer.DVE) if (onAirPiece === undefined && dataPiece !== undefined) { await context.stopPieceInstances([dataPiece._id]) @@ -1033,7 +1027,7 @@ async function executeActionSelectJingle< jingle.EndAlpha ) - const piece = literal({ + const piece: IBlueprintPiece = { externalId: `${externalId}-JINGLE`, name: userData.clip, enable: { @@ -1050,41 +1044,19 @@ async function executeActionSelectJingle< TallyTags.JINGLE_IS_LIVE, TallyTags.JINGLE ] - }) - - const jingleDataStore = settings.SelectedAdlibs.SourceLayer.Effekt - ? literal({ - externalId, - name: userData.clip, - enable: { - start: 0 - }, - outputLayerId: settings.SelectedAdlibs.OutputLayer.SelectedAdLib, - sourceLayerId: settings.SelectedAdlibs.SourceLayer.Effekt, - lifespan: PieceLifespan.WithinPart, - metaData: { - userData - }, - content: { - ...pieceContent, - timelineObjects: [] - }, - tags: [GetTagForJingleNext(userData.segmentExternalId, userData.clip)] - }) - : undefined + } settings.postProcessPieceTimelineObjects(context, config, piece, false) - const part = literal({ + const part: IBlueprintPart = { externalId, title: `JINGLE ${userData.clip}`, metaData: {}, ...props - }) + } await context.queuePart(part, [ piece, - ...(jingleDataStore ? [] : []), ...(settings.SelectedAdlibs ? await getPiecesToPreserve( context, @@ -1112,12 +1084,12 @@ async function executeActionCutToCamera< const externalId = generateExternalId(context, actionId, [userData.sourceDefinition.name]) - const part = literal({ + const part: IBlueprintPart = { externalId, title: userData.sourceDefinition.name, metaData: {}, expectedDuration: 0 - }) + } const sourceInfoCam = findSourceInfo(config.sources, userData.sourceDefinition) if (sourceInfoCam === undefined) { @@ -1134,7 +1106,7 @@ async function executeActionCutToCamera< const camSisyfos = GetSisyfosTimelineObjForCamera(config, sourceInfoCam, false) - const kamPiece = literal({ + const kamPiece: IBlueprintPiece = { externalId, name: part.title, enable: { start: 0 }, @@ -1142,11 +1114,11 @@ async function executeActionCutToCamera< sourceLayerId: settings.SourceLayers.Cam, lifespan: PieceLifespan.WithinPart, metaData: { - sisyfosPersistMetaData: literal({ + sisyfosPersistMetaData: { sisyfosLayers: [], acceptPersistAudio: sourceInfoCam.acceptPersistAudio, isPieceInjectedInPart: true - }) + } }, tags: [GetTagForKam(userData.sourceDefinition)], content: { @@ -1169,7 +1141,7 @@ async function executeActionCutToCamera< ...camSisyfos ]) } - }) + } settings.postProcessPieceTimelineObjects(context, config, kamPiece, false) @@ -1187,10 +1159,12 @@ async function executeActionCutToCamera< } else if (currentKam) { kamPiece.externalId = currentKam.piece.externalId kamPiece.enable = currentKam.piece.enable - const currentMetaData = currentKam.piece.metaData as PieceMetaData - const metaData = kamPiece.metaData as PieceMetaData + const currentMetaData = currentKam.piece.metaData! + const metaData = kamPiece.metaData! metaData.sisyfosPersistMetaData!.previousPersistMetaDataForCurrentPiece = currentMetaData.sisyfosPersistMetaData + await stopGraphicPiecesThatShouldEndWithPart(context, currentPieceInstances) + await context.updatePieceInstance(currentKam._id, kamPiece) } else { const currentExternalId = await context @@ -1211,12 +1185,32 @@ async function executeActionCutToCamera< ...(settings.SourceLayers.EVS ? [settings.SourceLayers.EVS] : []), settings.SourceLayers.Continuity ]) + await stopGraphicPiecesThatShouldEndWithPart(context, currentPieceInstances) kamPiece.enable = { start: 'now' } await context.insertPiece('current', kamPiece) } } +async function stopGraphicPiecesThatShouldEndWithPart( + context: ITV2ActionExecutionContext, + currentPieceInstances: Array> +) { + await context.stopPieceInstances( + currentPieceInstances + .filter(pieceInstance => isGraphicThatShouldEndWithPart(pieceInstance)) + .map(pieceInstance => pieceInstance._id) + ) +} + +function isGraphicThatShouldEndWithPart(pieceInstance: IBlueprintPieceInstance): boolean { + return ( + pieceInstance.piece.lifespan === PieceLifespan.WithinPart && + !pieceInstance.stoppedPlayback && + (STOPPABLE_GRAPHICS_LAYERS as string[]).includes(pieceInstance.piece.sourceLayerId) + ) +} + async function executeActionCutToRemote< StudioConfig extends TV2StudioConfigBase, ShowStyleConfig extends TV2BlueprintConfigBase @@ -1232,12 +1226,12 @@ async function executeActionCutToRemote< const title = userData.sourceDefinition.name - const part = literal({ + const part: IBlueprintPart = { externalId, title, metaData: {}, expectedDuration: 0 - }) + } const sourceInfo = findSourceInfo(config.sources, userData.sourceDefinition) if (sourceInfo === undefined) { @@ -1256,7 +1250,7 @@ async function executeActionCutToRemote< } : { sisyfosLayers: [] } - const remotePiece = literal({ + const remotePiece: IBlueprintPiece = { externalId, name: title, enable: { @@ -1290,7 +1284,7 @@ async function executeActionCutToRemote< ...eksternSisyfos ]) } - }) + } settings.postProcessPieceTimelineObjects(context, config, remotePiece, false) @@ -1334,21 +1328,20 @@ async function executeActionCutSourceToBox< ) let modify: undefined | 'current' | 'next' - let modifiedPiece: IBlueprintPieceInstance | undefined + let modifiedPiece: IBlueprintPieceInstance | undefined let modifiedDataStore: IBlueprintPieceInstance | undefined if (currentDVE && !currentDVE.stoppedPlayback) { modify = 'current' - modifiedPiece = currentDVE + modifiedPiece = currentDVE as IBlueprintPieceInstance modifiedDataStore = currentDataStore } else if (nextDVE) { modify = 'next' - modifiedPiece = nextDVE + modifiedPiece = nextDVE as IBlueprintPieceInstance modifiedDataStore = nextDataStore } - const meta: (DVEPieceMetaData & PieceMetaData) | undefined = modifiedPiece?.piece.metaData as PieceMetaData & - DVEPieceMetaData + const meta = modifiedPiece?.piece.metaData if ( !modifiedPiece || @@ -1390,7 +1383,11 @@ async function executeActionCutSourceToBox< mediaPlayerSession ) - let newDVEPiece: IBlueprintPiece = { ...modifiedPiece.piece, content: newPieceContent.content, metaData: meta } + let newDVEPiece: IBlueprintPiece = { + ...modifiedPiece.piece, + content: newPieceContent.content, + metaData: meta + } if (!containsServerBefore || !containsServerAfter) { newDVEPiece = await cutServerToBox(context, settings, newDVEPiece, !!containsServerBefore, modify === 'current') } @@ -1414,10 +1411,10 @@ async function executeActionCutSourceToBox< } interface PiecesBySourceLayer { - [key: string]: IBlueprintPieceInstance[] + [key: string]: Array> } -function groupPiecesBySourceLayer(pieceInstances: IBlueprintPieceInstance[]): PiecesBySourceLayer { +function groupPiecesBySourceLayer(pieceInstances: Array>): PiecesBySourceLayer { const piecesBySourceLayer: PiecesBySourceLayer = {} pieceInstances.forEach(piece => { if (!piecesBySourceLayer[piece.piece.sourceLayerId]) { @@ -1494,7 +1491,7 @@ async function executeActionTakeWithTransition< ) { const externalId = generateExternalId(context, actionId, [userData.variant.type]) - const nextPieces: IBlueprintPieceInstance[] = await context.getPieceInstances('next') + const nextPieces = await context.getPieceInstances('next') const nextPiecesBySourceLayer = groupPiecesBySourceLayer(nextPieces) const primaryPiece = findPrimaryPieceUsingPriority(settings, nextPiecesBySourceLayer) @@ -1544,7 +1541,7 @@ async function executeActionTakeWithTransition< await context.updatePieceInstance(primaryPiece._id, primaryPiece.piece) - const cutTransitionPiece: IBlueprintPiece = { + const cutTransitionPiece: IBlueprintPiece = { enable: { start: 0, duration: 1000 @@ -1577,7 +1574,7 @@ async function executeActionTakeWithTransition< await context.updatePieceInstance(primaryPiece._id, primaryPiece.piece) const config = settings.getConfig(context) - const pieces: IBlueprintPiece[] = [] + const pieces: Array> = [] partProps = CreateEffektForPartInner( context, config, @@ -1608,7 +1605,7 @@ async function executeActionTakeWithTransition< timelineObjectIndex ) - const blueprintPiece: IBlueprintPiece = CreateMixTransitionBlueprintPieceForPart( + const blueprintPiece = CreateMixTransitionBlueprintPieceForPart( externalId, userData.variant.frames, settings.SourceLayers.Effekt @@ -1630,7 +1627,7 @@ async function executeActionTakeWithTransition< primaryPiece, timelineObjectIndex ) - const blueprintPiece: IBlueprintPiece = CreateDipTransitionBlueprintPieceForPart( + const blueprintPiece = CreateDipTransitionBlueprintPieceForPart( externalId, userData.variant.frames, settings.SourceLayers.Effekt @@ -1653,7 +1650,7 @@ async function updateTimelineObjectMeTransition( timelineObject: TSR.TimelineObjAtemME, transitionStyle: TSR.AtemTransitionStyle, transitionSettings: TSR.AtemTransitionSettings, - pieceInstance: IBlueprintPieceInstance, + pieceInstance: IBlueprintPieceInstance, indexOfTimelineObject: number ): Promise { timelineObject.content.me.transition = transitionStyle @@ -1666,7 +1663,7 @@ async function updateTimelineObjectMeTransition( async function findPieceToRecoverDataFrom( context: ITV2ActionExecutionContext, dataStoreLayers: string[] -): Promise<{ piece: IBlueprintPieceInstance; part: 'current' | 'next' } | undefined> { +): Promise<{ piece: IBlueprintPieceInstance; part: 'current' | 'next' } | undefined> { const pieces = await Promise.all([context.getPieceInstances('current'), context.getPieceInstances('next')]) const currentPieces = pieces[0] const nextPieces = pieces[1] @@ -1675,7 +1672,7 @@ async function findPieceToRecoverDataFrom( const nextServer = nextPieces.find(p => dataStoreLayers.includes(p.piece.sourceLayerId)) - let pieceToRecoverDataFrom: IBlueprintPieceInstance | undefined + let pieceToRecoverDataFrom: IBlueprintPieceInstance | undefined let part: 'current' | 'next' = 'current' @@ -1683,7 +1680,6 @@ async function findPieceToRecoverDataFrom( part = 'next' pieceToRecoverDataFrom = nextServer } else if (currentServer) { - part = 'current' pieceToRecoverDataFrom = currentServer } @@ -1723,7 +1719,7 @@ async function findMediaPlayerSessions( } } - const sessions = (mediaPlayerSessionPiece.piece.piece.metaData as any)?.mediaPlayerSessions + const sessions = mediaPlayerSessionPiece.piece.piece.metaData?.mediaPlayerSessions return { // Assume there will be only one session @@ -1852,17 +1848,20 @@ async function executeActionRecallLastLive< const lastIdent = await context.findLastPieceOnLayer(settings.SourceLayers.Ident, { originalOnly: true, - excludeCurrentPart: false + excludeCurrentPart: false, + pieceMetaDataFilter: { + belongsToRemotePart: true + } }) const externalId = generateExternalId(context, actionId, [lastLive.piece.name]) - const part = literal({ + const part: IBlueprintPart = { externalId, title: lastLive.piece.name - }) + } - const pieces: IBlueprintPiece[] = [] + const pieces: Array> = [] pieces.push({ ...lastLive.piece, externalId, @@ -1872,12 +1871,10 @@ async function executeActionRecallLastLive< lifespan: PieceLifespan.WithinPart }) - // externalId should be replaced with something more concrete like partInstanceId - if (lastIdent && lastIdent.piece.externalId === lastLive.piece.externalId) { + if (lastIdent) { pieces.push({ ...lastIdent.piece, externalId, - enable: { ...lastIdent.piece.enable, start: 0 }, lifespan: PieceLifespan.WithinPart }) } @@ -1900,12 +1897,9 @@ async function executeActionRecallLastDVE< return } - const lastPlayedScheduledDVE: IBlueprintPieceInstance | undefined = await context.findLastPieceOnLayer( - settings.SourceLayers.DVE, - { - originalOnly: true - } - ) + const lastPlayedScheduledDVE = (await context.findLastPieceOnLayer(settings.SourceLayers.DVE, { + originalOnly: true + })) as IBlueprintPieceInstance | undefined const isLastPlayedAScheduledDVE: boolean = !lastPlayedScheduledDVE?.dynamicallyInserted if (lastPlayedScheduledDVE && isLastPlayedAScheduledDVE) { @@ -1920,16 +1914,16 @@ async function executeActionFadeDownPersistedAudioLevels< ShowStyleConfig extends TV2BlueprintConfigBase >(context: ITV2ActionExecutionContext, _settings: ActionExecutionSettings) { const fadeSisyfosMetaData = await createFadeSisyfosLevelsMetaData(context) - const resetSisyfosPersistedLevelsPiece: IBlueprintPiece = { + const resetSisyfosPersistedLevelsPiece: IBlueprintPiece = { externalId: 'fadeSisyfosPersistedLevelsDown', name: FADE_SISYFOS_LEVELS_PIECE_NAME, outputLayerId: '', sourceLayerId: '', enable: { start: 'now' }, lifespan: PieceLifespan.WithinPart, - metaData: literal({ + metaData: { sisyfosPersistMetaData: fadeSisyfosMetaData - }), + }, content: { timelineObjects: [] } @@ -1938,7 +1932,7 @@ async function executeActionFadeDownPersistedAudioLevels< } async function createFadeSisyfosLevelsMetaData(context: ITV2ActionExecutionContext) { - const resolvedPieceInstances: IBlueprintResolvedPieceInstance[] = await context.getResolvedPieceInstances('current') + const resolvedPieceInstances = await context.getResolvedPieceInstances('current') const emptySisyfosMetaData: SisyfosPersistMetaData = { sisyfosLayers: [] } @@ -1946,11 +1940,11 @@ async function createFadeSisyfosLevelsMetaData(context: ITV2ActionExecutionConte return emptySisyfosMetaData } - const latestPiece: IBlueprintResolvedPieceInstance = resolvedPieceInstances + const latestPiece = resolvedPieceInstances .filter(piece => piece.piece.name !== FADE_SISYFOS_LEVELS_PIECE_NAME) .sort((a, b) => b.resolvedStart - a.resolvedStart)[0] - const latestPieceMetaData = latestPiece.piece.metaData as PieceMetaData + const latestPieceMetaData = latestPiece.piece.metaData if (!latestPieceMetaData || !latestPieceMetaData.sisyfosPersistMetaData) { return emptySisyfosMetaData @@ -1963,38 +1957,6 @@ async function createFadeSisyfosLevelsMetaData(context: ITV2ActionExecutionConte } } -async function executeActionPlayGraphics< - StudioConfig extends TV2StudioConfigBase, - ShowStyleConfig extends TV2BlueprintConfigBase ->( - context: ITV2ActionExecutionContext, - settings: ActionExecutionSettings, - actionId: string, - userData: ActionPlayGraphics -): Promise { - if (!IsTargetingOVL(userData.graphic.target)) { - return - } - - const currentPartInstance = await context.getPartInstance('current') - const externalId = currentPartInstance?.part.externalId ?? generateExternalId(context, actionId, []) - - const internalGraphic: InternalGraphic = new InternalGraphic( - settings.getConfig(context), - userData.graphic, - { rank: 0 }, - externalId, - undefined - ) - const pieces: IBlueprintPiece[] = [] - - internalGraphic.createPiece(pieces) - - pieces.forEach((piece: IBlueprintPiece) => { - context.insertPiece('current', piece) - }) -} - async function scheduleLastPlayedDVE< StudioConfig extends TV2StudioConfigBase, ShowStyleConfig extends TV2BlueprintConfigBase @@ -2002,22 +1964,17 @@ async function scheduleLastPlayedDVE< context: ITV2ActionExecutionContext, settings: ActionExecutionSettings, actionId: string, - lastPlayedDVE: IBlueprintPieceInstance + lastPlayedDVE: IBlueprintPieceInstance ): Promise { - const lastPlayedDVEMeta: DVEPieceMetaData = lastPlayedDVE.piece.metaData as DVEPieceMetaData + const lastPlayedDVEMeta: DVEPieceMetaData = lastPlayedDVE.piece.metaData! const externalId: string = generateExternalId(context, actionId, [lastPlayedDVE.piece.name]) - await executeActionSelectDVE( - context, - settings, - actionId, - literal({ - type: AdlibActionType.SELECT_DVE, - config: lastPlayedDVEMeta.userData.config, - segmentExternalId: externalId, - videoId: lastPlayedDVEMeta.userData.videoId - }) - ) + await executeActionSelectDVE(context, settings, actionId, { + type: AdlibActionType.SELECT_DVE, + config: lastPlayedDVEMeta.userData.config, + segmentExternalId: externalId, + videoId: lastPlayedDVEMeta.userData.videoId + }) } async function scheduleNextScriptedDVE< @@ -2039,17 +1996,12 @@ async function scheduleNextScriptedDVE< const externalId: string = generateExternalId(context, actionId, [nextScriptedDVE.name]) const dveMeta: DVEPieceMetaData = nextScriptedDVE.metaData as DVEPieceMetaData - await executeActionSelectDVE( - context, - settings, - actionId, - literal({ - type: AdlibActionType.SELECT_DVE, - config: dveMeta.userData.config, - segmentExternalId: externalId, - videoId: dveMeta.userData.videoId - }) - ) + await executeActionSelectDVE(context, settings, actionId, { + type: AdlibActionType.SELECT_DVE, + config: dveMeta.userData.config, + segmentExternalId: externalId, + videoId: dveMeta.userData.videoId + }) } async function executeActionSelectFull< @@ -2065,7 +2017,8 @@ async function executeActionSelectFull< const template = GetFullGrafikTemplateName(config, userData.name) - const externalId = `adlib-action_${context.getHashId(`cut_to_full_${template}`)}` + const hash = context.getHashId(`cut_to_full_${template}`) + const externalId = `adlib-action_${hash}` const graphicType = config.studio.GraphicsType const previousPartKeepaliveDuration = @@ -2073,7 +2026,7 @@ async function executeActionSelectFull< ? config.studio.HTMLGraphics.KeepAliveDuration : config.studio.VizPilotGraphics.KeepAliveDuration - const part = literal({ + const part: IBlueprintPart = { externalId, title: `Full ${template}`, metaData: {}, @@ -2083,9 +2036,9 @@ async function executeActionSelectFull< partContentDelayDuration: 0, blockTakeDuration: 0 } - }) + } - const cue = literal>({ + const cue: CueDefinitionGraphic = { type: CueType.Graphic, target: 'FULL', graphic: { @@ -2095,7 +2048,7 @@ async function executeActionSelectFull< continueCount: -1 }, iNewsCommand: '' - }) + } const generator = new PilotGraphicGenerator({ config, @@ -2137,54 +2090,51 @@ async function executeActionClearGraphics< const config = settings.getConfig(context) await context.stopPiecesOnLayers(STOPPABLE_GRAPHICS_LAYERS) - await context.insertPiece( - 'current', - literal({ - enable: { - start: 'now', - duration: 3000 - }, - externalId: 'clearAllGFX', - name: userData.label, - sourceLayerId: SharedSourceLayers.PgmAdlibGraphicCmd, - outputLayerId: SharedOutputLayers.SEC, - lifespan: PieceLifespan.WithinPart, - content: - config.studio.GraphicsType === 'HTML' - ? { - timelineObjects: [ - literal({ - id: '', - enable: { - start: 0 - }, - priority: 1, - layer: SharedGraphicLLayer.GraphicLLayerAdLibs, - content: { - deviceType: TSR.DeviceType.ABSTRACT - } - }) - ] - } - : { - timelineObjects: [ - literal({ - id: '', - enable: { - start: 0 - }, - priority: 100, - layer: SharedGraphicLLayer.GraphicLLayerAdLibs, - content: { - deviceType: TSR.DeviceType.VIZMSE, - type: TSR.TimelineContentTypeVizMSE.CLEAR_ALL_ELEMENTS, - channelsToSendCommands: userData.sendCommands ? ['OVL1', 'FULL1', 'WALL1'] : undefined, - showId: config.selectedGraphicsSetup.OvlShowId - } - }) - ] - }, - tags: userData.sendCommands ? [TallyTags.GFX_CLEAR] : [TallyTags.GFX_ALTUD] - }) - ) + await context.insertPiece('current', { + enable: { + start: 'now', + duration: 3000 + }, + externalId: 'clearAllGFX', + name: userData.label, + sourceLayerId: SharedSourceLayers.PgmAdlibGraphicCmd, + outputLayerId: SharedOutputLayers.SEC, + lifespan: PieceLifespan.WithinPart, + content: + config.studio.GraphicsType === 'HTML' + ? { + timelineObjects: [ + literal({ + id: '', + enable: { + start: 0 + }, + priority: 1, + layer: SharedGraphicLLayer.GraphicLLayerAdLibs, + content: { + deviceType: TSR.DeviceType.ABSTRACT + } + }) + ] + } + : { + timelineObjects: [ + literal({ + id: '', + enable: { + start: 0 + }, + priority: 100, + layer: SharedGraphicLLayer.GraphicLLayerAdLibs, + content: { + deviceType: TSR.DeviceType.VIZMSE, + type: TSR.TimelineContentTypeVizMSE.CLEAR_ALL_ELEMENTS, + channelsToSendCommands: userData.sendCommands ? ['OVL1', 'FULL1', 'WALL1'] : undefined, + showId: config.selectedGraphicsSetup.OvlShowId + } + }) + ] + }, + tags: userData.sendCommands ? [TallyTags.GFX_CLEAR] : [TallyTags.GFX_ALTUD] + }) } diff --git a/src/tv2-common/content/dve.ts b/src/tv2-common/content/dve.ts index c4305b327..23795d3a8 100644 --- a/src/tv2-common/content/dve.ts +++ b/src/tv2-common/content/dve.ts @@ -21,6 +21,7 @@ import { JoinAssetToFolder, literal, PartDefinition, + PieceMetaData, TimelineBlueprintExt, TV2BlueprintConfigBase, TV2StudioConfigBase @@ -106,7 +107,7 @@ export interface DVEMetaData { mediaPlayerSession?: string } -export interface DVEPieceMetaData { +export interface DVEPieceMetaData extends PieceMetaData { config: DVEConfigInput sources: DVESources userData: ActionSelectDVE @@ -148,10 +149,6 @@ export function MakeContentDVEBase< } } - // console.log('boxmap1', boxMap) - // boxMap = boxMap.filter(map => map !== '') - // console.log('boxmap2', boxMap) - const graphicsTemplateContent: { [key: string]: string } = {} parsedCue.labels.forEach((label, i) => { graphicsTemplateContent[`${i}`] = label diff --git a/src/tv2-common/content/server.ts b/src/tv2-common/content/server.ts index 5c364ae66..0fed63153 100644 --- a/src/tv2-common/content/server.ts +++ b/src/tv2-common/content/server.ts @@ -79,10 +79,10 @@ function GetServerTimeline( sourceLayers: MakeContentServerSourceLayers, partProps: ServerPartProps, contentProps: ServerContentProps -) { +): TimelineObjectCoreExt[] { const serverEnableClass = `.${GetEnableClassForServer(contentProps.mediaPlayerSession)}` - const mediaObj = literal({ + const mediaObj: TSR.TimelineObjCCGMedia & TimelineBlueprintExt = { id: '', enable: { while: serverEnableClass @@ -106,7 +106,7 @@ function GetServerTimeline( ? [ServerParentClass('studio0', contentProps.file)] : []) ] - }) + } const mediaOffObj = JSON.parse(JSON.stringify(mediaObj)) as TSR.TimelineObjCCGMedia & TimelineBlueprintExt mediaOffObj.enable = { while: `!${serverEnableClass}` } @@ -115,7 +115,7 @@ function GetServerTimeline( const audioEnable = { while: serverEnableClass } - return literal([ + return [ mediaObj, mediaOffObj, ...GetSisyfosTimelineObjForServer( @@ -147,7 +147,7 @@ function GetServerTimeline( }) ] : []) - ]) + ] } export function CutToServer( diff --git a/src/tv2-common/cueTiming.ts b/src/tv2-common/cueTiming.ts index ee935c288..168ec0a1c 100644 --- a/src/tv2-common/cueTiming.ts +++ b/src/tv2-common/cueTiming.ts @@ -38,22 +38,14 @@ export function CreateTimingEnable( lifespan: PieceLifespan.WithinPart } - if (cue.start) { - ;(result.enable as any).start = CalculateTime(cue.start) - } else { - ;(result.enable as any).start = 0 - } + result.enable.start = (cue.start && CalculateTime(cue.start)) ?? 0 if (cue.end) { if (cue.end.infiniteMode) { result.lifespan = LifeSpan(cue.end.infiniteMode, PieceLifespan.WithinPart) } else { const end = CalculateTime(cue.end) - ;(result.enable as any).duration = end - ? result.enable.start - ? end - Number(result.enable.start) - : end - : undefined + result.enable.duration = end ? end - result.enable.start : undefined } } else if (defaultOut !== undefined) { result.enable.duration = defaultOut diff --git a/src/tv2-common/cues/ekstern.ts b/src/tv2-common/cues/ekstern.ts index afdb863b6..a10891f19 100644 --- a/src/tv2-common/cues/ekstern.ts +++ b/src/tv2-common/cues/ekstern.ts @@ -17,7 +17,7 @@ import { literal, PartDefinition, PartToParentClass, - SisyfosPersistMetaData, + PieceMetaData, TransitionSettings, TV2BlueprintConfigBase, TV2StudioConfigBase @@ -43,8 +43,8 @@ export function EvaluateEksternBase< context: IShowStyleUserContext, config: ShowStyleConfig, part: IBlueprintPart, - pieces: IBlueprintPiece[], - adlibPieces: IBlueprintAdLibPiece[], + pieces: Array>, + adlibPieces: Array>, partId: string, parsedCue: CueDefinitionEkstern, partDefinition: PartDefinition, @@ -61,105 +61,101 @@ export function EvaluateEksternBase< const atemInput = sourceInfoEkstern.port if (adlib) { - adlibPieces.push( - literal({ - _rank: rank || 0, - externalId: partId, - name: parsedCue.sourceDefinition.name, - outputLayerId: SharedOutputLayers.PGM, - sourceLayerId: layersEkstern.SourceLayer.PgmLive, - toBeQueued: true, - lifespan: PieceLifespan.WithinPart, - metaData: { - sisyfosPersistMetaData: literal({ - sisyfosLayers: sourceInfoEkstern.sisyfosLayers ?? [], - wantsToPersistAudio: sourceInfoEkstern.wantsToPersistAudio, - acceptPersistAudio: sourceInfoEkstern.acceptPersistAudio - }) - }, - content: literal>({ - studioLabel: '', - switcherInput: atemInput, - timelineObjects: literal([ - literal({ - id: '', - enable: { - start: 0 - }, - priority: 1, - layer: layersEkstern.ATEM.MEProgram, - content: { - deviceType: TSR.DeviceType.ATEM, - type: TSR.TimelineContentTypeAtem.ME, - me: { - input: atemInput, - transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, - transitionSettings: TransitionSettings(config, partDefinition) - } - }, - classes: [ControlClasses.LiveSourceOnAir] - }), + adlibPieces.push({ + _rank: rank || 0, + externalId: partId, + name: parsedCue.sourceDefinition.name, + outputLayerId: SharedOutputLayers.PGM, + sourceLayerId: layersEkstern.SourceLayer.PgmLive, + toBeQueued: true, + lifespan: PieceLifespan.WithinPart, + metaData: { + sisyfosPersistMetaData: { + sisyfosLayers: sourceInfoEkstern.sisyfosLayers ?? [], + wantsToPersistAudio: sourceInfoEkstern.wantsToPersistAudio, + acceptPersistAudio: sourceInfoEkstern.acceptPersistAudio + } + }, + content: literal>({ + studioLabel: '', + switcherInput: atemInput, + timelineObjects: literal([ + literal({ + id: '', + enable: { + start: 0 + }, + priority: 1, + layer: layersEkstern.ATEM.MEProgram, + content: { + deviceType: TSR.DeviceType.ATEM, + type: TSR.TimelineContentTypeAtem.ME, + me: { + input: atemInput, + transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, + transitionSettings: TransitionSettings(config, partDefinition) + } + }, + classes: [ControlClasses.LiveSourceOnAir] + }), - ...GetSisyfosTimelineObjForRemote(config, sourceInfoEkstern) - ]) - }) + ...GetSisyfosTimelineObjForRemote(config, sourceInfoEkstern) + ]) }) - ) + }) } else { - pieces.push( - literal({ - externalId: partId, - name: parsedCue.sourceDefinition.name, - enable: { - start: 0 - }, - outputLayerId: SharedOutputLayers.PGM, - sourceLayerId: layersEkstern.SourceLayer.PgmLive, - lifespan: PieceLifespan.WithinPart, - toBeQueued: true, - metaData: { - sisyfosPersistMetaData: literal({ - sisyfosLayers: sourceInfoEkstern.sisyfosLayers ?? [], - wantsToPersistAudio: sourceInfoEkstern.wantsToPersistAudio, - acceptPersistAudio: sourceInfoEkstern.acceptPersistAudio - }) - }, - tags: [GetTagForLive(parsedCue.sourceDefinition)], - content: literal>({ - studioLabel: '', - switcherInput: atemInput, - timelineObjects: literal([ - createEmptyObject({ - // Only want the ident for original versions (or clones) - enable: { start: 0 }, - layer: 'ekstern_enable_ident', - classes: [ControlClasses.ShowIdentGraphic, PartToParentClass('studio0', partDefinition) ?? ''] - }), - literal({ - id: '', - enable: { - start: 0 - }, - priority: 1, - layer: layersEkstern.ATEM.MEProgram, - content: { - deviceType: TSR.DeviceType.ATEM, - type: TSR.TimelineContentTypeAtem.ME, - me: { - input: atemInput, - transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, - transitionSettings: TransitionSettings(config, partDefinition) - } - }, - ...(AddParentClass(config, partDefinition) - ? { classes: [EksternParentClass('studio0', parsedCue.sourceDefinition.name)] } - : {}) - }), + pieces.push({ + externalId: partId, + name: parsedCue.sourceDefinition.name, + enable: { + start: 0 + }, + outputLayerId: SharedOutputLayers.PGM, + sourceLayerId: layersEkstern.SourceLayer.PgmLive, + lifespan: PieceLifespan.WithinPart, + toBeQueued: true, + metaData: { + sisyfosPersistMetaData: { + sisyfosLayers: sourceInfoEkstern.sisyfosLayers ?? [], + wantsToPersistAudio: sourceInfoEkstern.wantsToPersistAudio, + acceptPersistAudio: sourceInfoEkstern.acceptPersistAudio + } + }, + tags: [GetTagForLive(parsedCue.sourceDefinition)], + content: literal>({ + studioLabel: '', + switcherInput: atemInput, + timelineObjects: literal([ + createEmptyObject({ + // Only want the ident for original versions (or clones) + enable: { start: 0 }, + layer: 'ekstern_enable_ident', + classes: [PartToParentClass('studio0', partDefinition) ?? ''] + }), + literal({ + id: '', + enable: { + start: 0 + }, + priority: 1, + layer: layersEkstern.ATEM.MEProgram, + content: { + deviceType: TSR.DeviceType.ATEM, + type: TSR.TimelineContentTypeAtem.ME, + me: { + input: atemInput, + transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, + transitionSettings: TransitionSettings(config, partDefinition) + } + }, + ...(AddParentClass(config, partDefinition) + ? { classes: [EksternParentClass('studio0', parsedCue.sourceDefinition.name)] } + : {}) + }), - ...GetSisyfosTimelineObjForRemote(config, sourceInfoEkstern) - ]) - }) + ...GetSisyfosTimelineObjForRemote(config, sourceInfoEkstern) + ]) }) - ) + }) } } diff --git a/src/tv2-common/cues/lyd.ts b/src/tv2-common/cues/lyd.ts index 229c1d4bc..b19456688 100644 --- a/src/tv2-common/cues/lyd.ts +++ b/src/tv2-common/cues/lyd.ts @@ -59,44 +59,40 @@ export function EvaluateLYD( const lifespan = stop || fade || parsedCue.end ? PieceLifespan.WithinPart : PieceLifespan.OutOnRundownChange if (adlib) { - adlibPieces.push( - literal({ - _rank: rank || 0, - externalId: part.externalId, - name: parsedCue.variant, - outputLayerId: SharedOutputLayers.MUSIK, - sourceLayerId: SharedSourceLayers.PgmAudioBed, - lifespan, - expectedDuration: stop - ? 2000 - : fade - ? Math.max(1000, fadeIn ? TimeFromFrames(fadeIn) : 0) - : CreateTimingEnable(parsedCue).enable.duration ?? undefined, - content: LydContent(config, file, lydType, fadeIn, fadeOut), - tags: [AdlibTags.ADLIB_FLOW_PRODUCER] - }) - ) + adlibPieces.push({ + _rank: rank || 0, + externalId: part.externalId, + name: parsedCue.variant, + outputLayerId: SharedOutputLayers.MUSIK, + sourceLayerId: SharedSourceLayers.PgmAudioBed, + lifespan, + expectedDuration: stop + ? 2000 + : fade + ? Math.max(1000, fadeIn ? TimeFromFrames(fadeIn) : 0) + : CreateTimingEnable(parsedCue).enable.duration ?? undefined, + content: LydContent(config, file, lydType, fadeIn, fadeOut), + tags: [AdlibTags.ADLIB_FLOW_PRODUCER] + }) } else { - pieces.push( - literal({ - externalId: part.externalId, - name: parsedCue.variant, - ...(stop - ? { enable: { start: CreateTimingEnable(parsedCue).enable.start, duration: 2000 } } - : fade - ? { - enable: { - start: CreateTimingEnable(parsedCue).enable.start, - duration: Math.max(1000, fadeIn ? TimeFromFrames(fadeIn) : 0) - } - } - : CreateTimingEnable(parsedCue)), - outputLayerId: SharedOutputLayers.MUSIK, - sourceLayerId: SharedSourceLayers.PgmAudioBed, - lifespan, - content: LydContent(config, file, lydType, fadeIn, fadeOut) - }) - ) + pieces.push({ + externalId: part.externalId, + name: parsedCue.variant, + ...(stop + ? { enable: { start: CreateTimingEnable(parsedCue).enable.start, duration: 2000 } } + : fade + ? { + enable: { + start: CreateTimingEnable(parsedCue).enable.start, + duration: Math.max(1000, fadeIn ? TimeFromFrames(fadeIn) : 0) + } + } + : CreateTimingEnable(parsedCue)), + outputLayerId: SharedOutputLayers.MUSIK, + sourceLayerId: SharedSourceLayers.PgmAudioBed, + lifespan, + content: LydContent(config, file, lydType, fadeIn, fadeOut) + }) } } diff --git a/src/tv2-common/cues/mixMinus.ts b/src/tv2-common/cues/mixMinus.ts index eb29881f7..abf057a1c 100644 --- a/src/tv2-common/cues/mixMinus.ts +++ b/src/tv2-common/cues/mixMinus.ts @@ -28,23 +28,21 @@ export function EvaluateCueMixMinus( } const atemInput = sourceInfo.port - pieces.push( - literal({ - externalId: part.externalId, - name: `MixMinus: ${name}`, - enable: { - start: 0 - }, - lifespan: PieceLifespan.OutOnShowStyleEnd, - sourceLayerId: SharedSourceLayers.AuxMixMinus, - outputLayerId: SharedOutputLayers.AUX, - content: MixMinusContent(atemInput) - }) - ) + pieces.push({ + externalId: part.externalId, + name: `MixMinus: ${name}`, + enable: { + start: 0 + }, + lifespan: PieceLifespan.OutOnShowStyleEnd, + sourceLayerId: SharedSourceLayers.AuxMixMinus, + outputLayerId: SharedOutputLayers.AUX, + content: MixMinusContent(atemInput) + }) } function MixMinusContent(atemInput: number): WithTimeline { - return literal>({ + return { timelineObjects: literal([ literal({ content: { @@ -62,5 +60,5 @@ function MixMinusContent(atemInput: number): WithTimeline { priority: 1 }) ]) - }) + } } diff --git a/src/tv2-common/evaluateCues.ts b/src/tv2-common/evaluateCues.ts index 6eb710f43..b5191ef41 100644 --- a/src/tv2-common/evaluateCues.ts +++ b/src/tv2-common/evaluateCues.ts @@ -181,7 +181,7 @@ export interface EvaluateCuesOptions { /** Whether the parent part is a graphic part. */ isGrafikPart?: boolean /** Passing this arguments sets the types of cues to evaluate. */ - selectedCueTypes?: CueType[] | undefined + selectedCueTypes?: CueType[] /** Don't evaluate adlibs. */ excludeAdlibs?: boolean /** Only evaluate adlibs. */ diff --git a/src/tv2-common/getSegment.ts b/src/tv2-common/getSegment.ts index 5b70b9ce6..4593e333b 100644 --- a/src/tv2-common/getSegment.ts +++ b/src/tv2-common/getSegment.ts @@ -109,7 +109,7 @@ export async function getSegmentBase< ): Promise { const segmentPayload = ingestSegment.payload as INewsPayload | undefined const iNewsStory = segmentPayload?.iNewsStory - const segment = literal({ + const segment: IBlueprintSegment = { name: ingestSegment.name || '', metaData: {}, showShelf: false, @@ -117,7 +117,7 @@ export async function getSegmentBase< iNewsStory && iNewsStory.fields.pageNumber && iNewsStory.fields.pageNumber.trim() ? iNewsStory.fields.pageNumber.trim() : undefined - }) + } const config = showStyleOptions.getConfig(context) if (!segmentPayload || !iNewsStory || iNewsStory.meta.float === 'float' || !iNewsStory.body) { @@ -292,11 +292,11 @@ export async function getSegmentBase< if (!part.part.expectedDuration && totalTimeMs > 0) { part.part.expectedDuration = (totalTimeMs - allocatedTime || 0) / partsWithoutExpectedDuration - if (part.part.expectedDuration! < 0) { + if (part.part.expectedDuration < 0) { part.part.expectedDuration = 0 } - if (part.part.expectedDuration! > config.studio.MaximumPartDuration) { + if (part.part.expectedDuration > config.studio.MaximumPartDuration) { part.part.expectedDuration = config.studio.MaximumPartDuration } } diff --git a/src/tv2-common/helpers/__tests__/serverResume.spec.ts b/src/tv2-common/helpers/__tests__/serverResume.spec.ts index 67e893531..feb317794 100644 --- a/src/tv2-common/helpers/__tests__/serverResume.spec.ts +++ b/src/tv2-common/helpers/__tests__/serverResume.spec.ts @@ -6,7 +6,7 @@ import { VTContent, WithTimeline } from '@tv2media/blueprints-integration' -import { DVEPieceMetaData, literal, RemoteType, SourceDefinitionRemote } from 'tv2-common' +import { DVEPieceMetaData, literal, PieceMetaData, RemoteType, SourceDefinitionRemote } from 'tv2-common' import { SharedSourceLayers, SourceType } from 'tv2-constants' import { getServerPositionForPartInstance } from '../serverResume' @@ -36,7 +36,7 @@ function getMockPartInstance(partInstance: Partial): IBl describe('Server Resume', () => { it('Returns server position from server part with resolved duration', () => { const position = getServerPositionForPartInstance(getMockPartInstance({ _id: 'mock_1' }), [ - literal({ + literal>({ _id: '', partInstanceId: 'mock_1', resolvedStart: 1000, @@ -64,7 +64,7 @@ describe('Server Resume', () => { const position = getServerPositionForPartInstance( getMockPartInstance({ _id: 'mock_1', timings: { startedPlayback: 1000 } }), [ - literal({ + literal>({ _id: '', partInstanceId: 'mock_1', startedPlayback: 1000, @@ -105,7 +105,7 @@ describe('Server Resume', () => { timings: { startedPlayback: 11000 } }), [ - literal({ + literal>({ _id: '', partInstanceId: 'mock_1', resolvedStart: 1000, @@ -151,7 +151,7 @@ describe('Server Resume', () => { timings: { startedPlayback: 11000 } }), [ - literal({ + literal>({ _id: '', partInstanceId: 'mock_1', resolvedStart: 1000, diff --git a/src/tv2-common/helpers/abPlayback.ts b/src/tv2-common/helpers/abPlayback.ts index 8ab82fcc2..db086d373 100644 --- a/src/tv2-common/helpers/abPlayback.ts +++ b/src/tv2-common/helpers/abPlayback.ts @@ -72,20 +72,19 @@ interface SessionTime { } function calculateSessionTimeRanges( _context: ITimelineEventContext, - resolvedPieces: IBlueprintResolvedPieceInstance[] + resolvedPieces: Array> ) { const piecesWantingMediaPlayers = _.filter(resolvedPieces, p => { if (!p.piece.metaData) { return false } - const metadata = p.piece.metaData as PieceMetaData - return (metadata.mediaPlayerSessions || []).length > 0 + return (p.piece.metaData.mediaPlayerSessions || []).length > 0 }) const sessionRequests: { [sessionId: string]: SessionTime | undefined } = {} _.each(piecesWantingMediaPlayers, p => { - const metadata = p.piece.metaData as PieceMetaData - const start = p.resolvedStart as number + const metadata = p.piece.metaData! + const start = p.resolvedStart const duration = p.resolvedDuration const end = duration !== undefined ? start + duration : undefined @@ -205,7 +204,7 @@ export function resolveMediaPlayerAssignments< context: ITimelineEventContext, config: ShowStyleConfig, previousAssignmentRev: SessionToPlayerMap, - resolvedPieces: IBlueprintResolvedPieceInstance[] + resolvedPieces: Array> ) { const debugLog = config.studio.ABPlaybackDebugLogging const sessionRequests = calculateSessionTimeRanges(context, resolvedPieces) @@ -370,7 +369,7 @@ export function assignMediaPlayers< config: ShowStyleConfig, timelineObjs: OnGenerateTimelineObj[], previousAssignment: TimelinePersistentStateExt['activeMediaPlayers'], - resolvedPieces: IBlueprintResolvedPieceInstance[], + resolvedPieces: Array>, sourceLayers: ABSourceLayers ): TimelinePersistentStateExt['activeMediaPlayers'] { const previousAssignmentRev = reversePreviousAssignment(previousAssignment, timelineObjs) diff --git a/src/tv2-common/helpers/graphics/InternalGraphic.ts b/src/tv2-common/helpers/graphics/InternalGraphic.ts index 856599c89..28218ea4b 100644 --- a/src/tv2-common/helpers/graphics/InternalGraphic.ts +++ b/src/tv2-common/helpers/graphics/InternalGraphic.ts @@ -1,33 +1,15 @@ -import { - IBlueprintActionManifest, - IBlueprintAdLibPiece, - IBlueprintPiece, - ICommonContext, - PieceLifespan, - TSR -} from '@tv2media/blueprints-integration' +import { IBlueprintAdLibPiece, IBlueprintPiece, PieceLifespan } from '@tv2media/blueprints-integration' import { Adlib } from 'tv2-common' import _ = require('underscore') -import { - AbstractLLayer, - AdlibActionType, - AdlibTags, - GraphicEngine, - SharedOutputLayers, - SharedSourceLayers -} from '../../../tv2-constants' -import { ActionPlayGraphics } from '../../actions' +import { AdlibTags, GraphicEngine, PartType, SharedOutputLayers, SharedSourceLayers } from '../../../tv2-constants' import { TV2BlueprintConfig } from '../../blueprintConfig' -import { GetDefaultOut } from '../../cueTiming' -import { CueDefinitionGraphic, GraphicInternal, IsStickyIdent, PartDefinition } from '../../inewsConversion' -import { PieceMetaData } from '../../onTimelineGenerate' -import { generateExternalId, literal } from '../../util' -import { t } from '../translation' +import { CueDefinitionGraphic, GraphicInternal, PartDefinition } from '../../inewsConversion' +import { GraphicPieceMetaData, PieceMetaData } from '../../onTimelineGenerate' import { GetInternalGraphicContentCaspar } from './caspar' import { GetSourceLayerForGraphic } from './layers' import { GetFullGraphicTemplateNameFromCue, GraphicDisplayName } from './name' -import { IsTargetingOVL, IsTargetingTLF, IsTargetingWall } from './target' -import { CreateTimingGraphic, GetInfiniteModeForGraphic } from './timing' +import { IsTargetingTLF, IsTargetingWall } from './target' +import { CreateTimingGraphic, GetPieceLifespanForGraphic } from './timing' import { GetInternalGraphicContentVIZ } from './viz' export class InternalGraphic { @@ -36,7 +18,6 @@ export class InternalGraphic { private readonly parsedCue: CueDefinitionGraphic private readonly partDefinition?: PartDefinition private readonly adlib?: Adlib - private readonly isStickyIdent: boolean private readonly engine: GraphicEngine private readonly name: string private readonly sourceLayerId: SharedSourceLayers @@ -52,201 +33,97 @@ export class InternalGraphic { partId?: string, partDefinition?: PartDefinition ) { - const isStickyIdent = IsStickyIdent(parsedCue) - - const engine = parsedCue.target - const mappedTemplate = GetFullGraphicTemplateNameFromCue(config, parsedCue) - const sourceLayerId = GetSourceLayerForGraphic(config, mappedTemplate, isStickyIdent) + const sourceLayerId = GetSourceLayerForGraphic(config, mappedTemplate) this.config = config this.parsedCue = parsedCue this.partDefinition = partDefinition this.adlib = adlib this.mappedTemplate = mappedTemplate - this.isStickyIdent = isStickyIdent this.engine = parsedCue.target this.name = GraphicDisplayName(config, parsedCue) this.sourceLayerId = sourceLayerId - this.outputLayerId = IsTargetingWall(engine) ? SharedOutputLayers.SEC : SharedOutputLayers.OVERLAY + this.outputLayerId = IsTargetingWall(this.engine) ? SharedOutputLayers.SEC : SharedOutputLayers.OVERLAY this.partId = partId this.content = this.getInternalGraphicContent() } - public createAdlibTargetingOVL( - context: ICommonContext, - actions: IBlueprintActionManifest[], - adlibPieces: IBlueprintAdLibPiece[] - ): void { - if (IsTargetingOVL(this.engine) && this.isStickyIdent) { - const userData = literal({ - type: AdlibActionType.PLAY_GRAPHICS, - graphic: this.parsedCue - }) - actions.push( - literal({ - externalId: generateExternalId(context, userData), - actionId: AdlibActionType.PLAY_GRAPHICS, - userData, - userDataManifest: {}, - display: { - _rank: this.rank || 0, - label: t(this.name), - uniquenessId: `gfx_${this.name}_${this.sourceLayerId}_${this.outputLayerId}_commentator`, - sourceLayerId: this.sourceLayerId, - outputLayerId: SharedOutputLayers.OVERLAY, - tags: [AdlibTags.ADLIB_KOMMENTATOR], - content: _.clone(this.content) - } - }) - ) - } else if (IsTargetingOVL(this.engine)) { - const adLibPiece = literal({ - _rank: this.rank || 0, - externalId: this.partId ?? '', - name: this.name, - uniquenessId: `gfx_${this.name}_${this.sourceLayerId}_${this.outputLayerId}_commentator`, - sourceLayerId: this.sourceLayerId, - outputLayerId: SharedOutputLayers.OVERLAY, - lifespan: PieceLifespan.WithinPart, - metaData: literal({ - sisyfosPersistMetaData: { - sisyfosLayers: [] - } - }), - expectedDuration: 5000, - tags: [AdlibTags.ADLIB_KOMMENTATOR], - content: _.clone(this.content) - }) - adlibPieces.push(adLibPiece) + public createCommentatorAdlib(): IBlueprintAdLibPiece { + return { + _rank: this.rank || 0, + externalId: this.partId ?? '', + name: this.name, + uniquenessId: `gfx_${this.name}_${this.sourceLayerId}_${this.outputLayerId}_commentator`, + sourceLayerId: this.sourceLayerId, + outputLayerId: SharedOutputLayers.OVERLAY, + lifespan: PieceLifespan.WithinPart, + metaData: { + sisyfosPersistMetaData: { + sisyfosLayers: [] + } + }, + expectedDuration: 5000, + tags: [AdlibTags.ADLIB_KOMMENTATOR], + content: _.clone(this.content) } } - public createAdlib( - context: ICommonContext, - actions: IBlueprintActionManifest[], - adlibPieces: IBlueprintAdLibPiece[] - ): void { - if (this.isStickyIdent) { - const userData = literal({ - type: AdlibActionType.PLAY_GRAPHICS, - graphic: this.parsedCue - }) - actions.push( - literal({ - externalId: generateExternalId(context, userData), - actionId: AdlibActionType.PLAY_GRAPHICS, - userData, - userDataManifest: {}, - display: { - _rank: this.rank || 0, - label: t(this.name), - uniquenessId: `gfx_${this.name}_${this.sourceLayerId}_${this.outputLayerId}_flow`, - sourceLayerId: this.sourceLayerId, - outputLayerId: SharedOutputLayers.OVERLAY, - tags: [AdlibTags.ADLIB_FLOW_PRODUCER], - content: _.clone(this.content) - } - }) - ) - } else { - adlibPieces.push( - literal({ - _rank: this.rank || 0, - externalId: this.partId ?? '', - name: this.name, - uniquenessId: `gfx_${this.name}_${this.sourceLayerId}_${this.outputLayerId}_flow`, - sourceLayerId: this.sourceLayerId, - outputLayerId: this.outputLayerId, - tags: [AdlibTags.ADLIB_FLOW_PRODUCER], - ...(IsTargetingTLF(this.engine) || (this.parsedCue.end && this.parsedCue.end.infiniteMode) - ? {} - : { - expectedDuration: - CreateTimingGraphic(this.config, this.parsedCue).duration || GetDefaultOut(this.config) - }), - lifespan: GetInfiniteModeForGraphic(this.engine, this.config, this.parsedCue, this.isStickyIdent), - metaData: literal({ - sisyfosPersistMetaData: { - sisyfosLayers: [] - } - }), - content: _.clone(this.content) - }) - ) + public createAdlib(): IBlueprintAdLibPiece { + return { + _rank: this.rank || 0, + externalId: this.partId ?? '', + name: this.name, + uniquenessId: `gfx_${this.name}_${this.sourceLayerId}_${this.outputLayerId}_flow`, + sourceLayerId: this.sourceLayerId, + outputLayerId: this.outputLayerId, + tags: [AdlibTags.ADLIB_FLOW_PRODUCER], + ...(IsTargetingTLF(this.engine) || (this.parsedCue.end && this.parsedCue.end.infiniteMode) + ? {} + : { + expectedDuration: CreateTimingGraphic(this.config, this.parsedCue).duration + }), + lifespan: GetPieceLifespanForGraphic(this.engine, this.config, this.parsedCue), + metaData: { + sisyfosPersistMetaData: { + sisyfosLayers: [] + } + }, + content: _.clone(this.content) } } - public createPiece(pieces: IBlueprintPiece[]): void { - const piece = literal({ + public createPiece(): IBlueprintPiece { + return { externalId: this.partId ?? '', name: this.name, ...(IsTargetingTLF(this.engine) || IsTargetingWall(this.engine) ? { enable: { start: 0 } } : { enable: { - ...CreateTimingGraphic(this.config, this.parsedCue, !this.isStickyIdent) + ...CreateTimingGraphic(this.config, this.parsedCue) } }), outputLayerId: this.outputLayerId, sourceLayerId: this.sourceLayerId, - lifespan: GetInfiniteModeForGraphic(this.engine, this.config, this.parsedCue, this.isStickyIdent), - metaData: literal({ + lifespan: GetPieceLifespanForGraphic(this.engine, this.config, this.parsedCue), + metaData: { sisyfosPersistMetaData: { sisyfosLayers: [] - } - }), + }, + belongsToRemotePart: this.partDefinition?.type === PartType.REMOTE + }, content: _.clone(this.content) - }) - pieces.push(piece) - - if ( - this.sourceLayerId === SharedSourceLayers.PgmGraphicsIdentPersistent && - (piece.lifespan === PieceLifespan.OutOnSegmentEnd || piece.lifespan === PieceLifespan.OutOnShowStyleEnd) && - this.isStickyIdent - ) { - // Special case for the ident. We want it to continue to exist in case the Live gets shown again, but we dont want the continuation showing in the ui. - // So we create the normal object on a hidden layer, and then clone it on another layer without content for the ui - pieces.push(this.createIndicatorPieceForIdentPersistent(piece)) } } - public createIndicatorPieceForIdentPersistent(piece: IBlueprintPiece): IBlueprintPiece { - return literal({ - ...piece, - enable: { ...CreateTimingGraphic(this.config, this.parsedCue, true) }, // Allow default out for visual representation - sourceLayerId: SharedSourceLayers.PgmGraphicsIdent, - lifespan: PieceLifespan.WithinPart, - metaData: literal({ - sisyfosPersistMetaData: { - sisyfosLayers: [] - } - }), - content: { - timelineObjects: [ - literal({ - id: '', - enable: { - while: '1' - }, - layer: AbstractLLayer.IdentMarker, - content: { - deviceType: TSR.DeviceType.ABSTRACT - } - }) - ] - } - }) - } - private getInternalGraphicContent(): IBlueprintPiece['content'] { return this.config.studio.GraphicsType === 'HTML' ? GetInternalGraphicContentCaspar( this.config, this.engine, this.parsedCue, - this.isStickyIdent, this.partDefinition, this.mappedTemplate, !!this.adlib @@ -255,7 +132,6 @@ export class InternalGraphic { this.config, this.engine, this.parsedCue, - this.isStickyIdent, this.partDefinition, this.mappedTemplate, !!this.adlib diff --git a/src/tv2-common/helpers/graphics/caspar/index.ts b/src/tv2-common/helpers/graphics/caspar/index.ts index 43ff6239f..96b34ce8b 100644 --- a/src/tv2-common/helpers/graphics/caspar/index.ts +++ b/src/tv2-common/helpers/graphics/caspar/index.ts @@ -32,21 +32,12 @@ export function GetInternalGraphicContentCaspar( config: TV2BlueprintConfig, engine: GraphicEngine, parsedCue: CueDefinitionGraphic, - isIdentGraphic: boolean, partDefinition: PartDefinition | undefined, mappedTemplate: string, adlib: boolean ): IBlueprintPiece['content'] { return { - timelineObjects: CasparOverlayTimeline( - config, - engine, - parsedCue, - isIdentGraphic, - partDefinition, - mappedTemplate, - adlib - ) + timelineObjects: CasparOverlayTimeline(config, engine, parsedCue, partDefinition, mappedTemplate, adlib) } } @@ -56,7 +47,7 @@ export function GetPilotGraphicContentCaspar( parsedCue: CueDefinitionGraphic, settings: CasparPilotGeneratorSettings, engine: GraphicEngine -) { +): WithTimeline { const graphicFolder = config.studio.GraphicFolder ? `${config.studio.GraphicFolder}\\` : '' const fileName = JoinAssetToFolder(config.studio.GraphicFolder, parsedCue.graphic.name) const templateData = { @@ -74,7 +65,7 @@ export function GetPilotGraphicContentCaspar( } } } - return literal>({ + return { fileName, path: JoinAssetToNetworkPath( config.studio.GraphicNetworkBasePath, @@ -109,14 +100,13 @@ export function GetPilotGraphicContentCaspar( }), ...(IsTargetingFull(engine) ? settings.createPilotTimelineForStudio(config, context) : []) ] - }) + } } function CasparOverlayTimeline( config: TV2BlueprintConfig, engine: GraphicEngine, parsedCue: CueDefinitionGraphic, - isIdentGrafik: boolean, partDefinition: PartDefinition | undefined, mappedTemplate: string, adlib: boolean @@ -124,7 +114,7 @@ function CasparOverlayTimeline( return [ literal({ id: '', - enable: GetEnableForGraphic(config, engine, parsedCue, isIdentGrafik, partDefinition, adlib), + enable: GetEnableForGraphic(config, engine, parsedCue, partDefinition, adlib), priority: 1, layer: GetTimelineLayerForGraphic(config, mappedTemplate), content: CreateHTMLRendererContent(config, mappedTemplate, { ...parsedCue.graphic.textFields }) diff --git a/src/tv2-common/helpers/graphics/design/index.ts b/src/tv2-common/helpers/graphics/design/index.ts index fd2adf6a8..2ca0b22cc 100644 --- a/src/tv2-common/helpers/graphics/design/index.ts +++ b/src/tv2-common/helpers/graphics/design/index.ts @@ -29,41 +29,37 @@ export function EvaluateDesignBase( } if (adlib) { - adlibPieces.push( - literal({ - _rank: rank || 0, - externalId: partId, - name: parsedCue.design, - outputLayerId: SharedOutputLayers.SEC, - sourceLayerId: SharedSourceLayers.PgmDesign, - lifespan: PieceLifespan.OutOnShowStyleEnd, - content: literal>({ - fileName: parsedCue.design, - path: parsedCue.design, - ignoreMediaObjectStatus: true, - timelineObjects: designTimeline(config, parsedCue) - }) + adlibPieces.push({ + _rank: rank || 0, + externalId: partId, + name: parsedCue.design, + outputLayerId: SharedOutputLayers.SEC, + sourceLayerId: SharedSourceLayers.PgmDesign, + lifespan: PieceLifespan.OutOnShowStyleEnd, + content: literal>({ + fileName: parsedCue.design, + path: parsedCue.design, + ignoreMediaObjectStatus: true, + timelineObjects: designTimeline(config, parsedCue) }) - ) + }) } else { - pieces.push( - literal({ - externalId: partId, - name: parsedCue.design, - enable: { - start - }, - outputLayerId: SharedOutputLayers.SEC, - sourceLayerId: SharedSourceLayers.PgmDesign, - lifespan: PieceLifespan.OutOnShowStyleEnd, - content: literal>({ - fileName: parsedCue.design, - path: parsedCue.design, - ignoreMediaObjectStatus: true, - timelineObjects: designTimeline(config, parsedCue) - }) + pieces.push({ + externalId: partId, + name: parsedCue.design, + enable: { + start + }, + outputLayerId: SharedOutputLayers.SEC, + sourceLayerId: SharedSourceLayers.PgmDesign, + lifespan: PieceLifespan.OutOnShowStyleEnd, + content: literal>({ + fileName: parsedCue.design, + path: parsedCue.design, + ignoreMediaObjectStatus: true, + timelineObjects: designTimeline(config, parsedCue) }) - ) + }) } } diff --git a/src/tv2-common/helpers/graphics/internal/index.ts b/src/tv2-common/helpers/graphics/internal/index.ts index 19e5b96c4..a38bd8cf8 100644 --- a/src/tv2-common/helpers/graphics/internal/index.ts +++ b/src/tv2-common/helpers/graphics/internal/index.ts @@ -1,10 +1,12 @@ +import { IBlueprintAdLibPiece, IBlueprintPiece, IShowStyleUserContext } from '@tv2media/blueprints-integration' import { - IBlueprintActionManifest, - IBlueprintAdLibPiece, - IBlueprintPiece, - IShowStyleUserContext -} from '@tv2media/blueprints-integration' -import { Adlib, CueDefinitionGraphic, GraphicInternal, PartDefinition, TV2BlueprintConfig } from 'tv2-common' + Adlib, + CueDefinitionGraphic, + GraphicInternal, + IsTargetingOVL, + PartDefinition, + TV2BlueprintConfig +} from 'tv2-common' import { InternalGraphic } from '../InternalGraphic' export function CreateInternalGraphic( @@ -12,7 +14,6 @@ export function CreateInternalGraphic( context: IShowStyleUserContext, pieces: IBlueprintPiece[], adlibPieces: IBlueprintAdLibPiece[], - actions: IBlueprintActionManifest[], partId: string, parsedCue: CueDefinitionGraphic, partDefinition: PartDefinition, @@ -26,9 +27,11 @@ export function CreateInternalGraphic( } if (adlib) { - internalGraphic.createAdlibTargetingOVL(context, actions, adlibPieces) - internalGraphic.createAdlib(context, actions, adlibPieces) + if (IsTargetingOVL(parsedCue.target)) { + adlibPieces.push(internalGraphic.createCommentatorAdlib()) + } + adlibPieces.push(internalGraphic.createAdlib()) } else { - internalGraphic.createPiece(pieces) + pieces.push(internalGraphic.createPiece()) } } diff --git a/src/tv2-common/helpers/graphics/layers.ts b/src/tv2-common/helpers/graphics/layers.ts index cb9b4967d..54e914b0a 100644 --- a/src/tv2-common/helpers/graphics/layers.ts +++ b/src/tv2-common/helpers/graphics/layers.ts @@ -1,7 +1,7 @@ import { TV2BlueprintConfig } from 'tv2-common' import { SharedGraphicLLayer, SharedSourceLayers } from 'tv2-constants' -export function GetSourceLayerForGraphic(config: TV2BlueprintConfig, name: string, isStickyIdent?: boolean) { +export function GetSourceLayerForGraphic(config: TV2BlueprintConfig, name: string) { const conf = config.showStyle.GFXTemplates ? config.showStyle.GFXTemplates.find(gfk => gfk.VizTemplate.toString() === name) : undefined @@ -19,10 +19,6 @@ export function GetSourceLayerForGraphic(config: TV2BlueprintConfig, name: strin } return SharedSourceLayers.PgmGraphicsHeadline case SharedSourceLayers.PgmGraphicsIdent: - if (isStickyIdent) { - return SharedSourceLayers.PgmGraphicsIdentPersistent - } - return SharedSourceLayers.PgmGraphicsIdent case SharedSourceLayers.PgmGraphicsLower: return SharedSourceLayers.PgmGraphicsLower diff --git a/src/tv2-common/helpers/graphics/name.ts b/src/tv2-common/helpers/graphics/name.ts index 63329eb42..e4a8bed78 100644 --- a/src/tv2-common/helpers/graphics/name.ts +++ b/src/tv2-common/helpers/graphics/name.ts @@ -34,13 +34,11 @@ export function GetFullGraphicTemplateNameFromCue( } export function GetFullGrafikTemplateName(config: TV2BlueprintConfig, iNewsTempalateName: string): string { - if (config.showStyle.GFXTemplates) { - const template = config.showStyle.GFXTemplates.find(templ => - templ.INewsName ? templ.INewsName.toString().toUpperCase() === iNewsTempalateName.toUpperCase() : false - ) - if (template && template.VizTemplate.toString().length) { - return template.VizTemplate.toString() - } + const template = config.showStyle.GFXTemplates.find(templ => + templ.INewsName ? templ.INewsName.toString().toUpperCase() === iNewsTempalateName.toUpperCase() : false + ) + if (template && template.VizTemplate.toString().length) { + return template.VizTemplate.toString() } // This means unconfigured templates will still be supported, with default out. diff --git a/src/tv2-common/helpers/graphics/pilot/index.ts b/src/tv2-common/helpers/graphics/pilot/index.ts index 99eb9f7ea..5308631c5 100644 --- a/src/tv2-common/helpers/graphics/pilot/index.ts +++ b/src/tv2-common/helpers/graphics/pilot/index.ts @@ -13,9 +13,10 @@ import { Adlib, CreateTimingGraphic, CueDefinitionGraphic, + FullPieceMetaData, generateExternalId, GetFullGraphicTemplateNameFromCue, - GetInfiniteModeForGraphic, + GetPieceLifespanForGraphic, GetPilotGraphicContentViz, GetTagForFull, GetTagForFullNext, @@ -111,18 +112,18 @@ export class PilotGraphicGenerator { this.segmentExternalId = graphicProps.segmentExternalId } - public createPilotAdLibAction() { + public createPilotAdLibAction(): IBlueprintActionManifest { const name = GraphicDisplayName(this.config, this.parsedCue) const sourceLayerId = this.getSourceLayer() const outputLayerId = this.getOutputLayer() - const userData = literal({ + const userData: ActionSelectFullGrafik = { type: AdlibActionType.SELECT_FULL_GRAFIK, name: this.parsedCue.graphic.name, vcpid: this.parsedCue.graphic.vcpid, segmentExternalId: this.segmentExternalId - }) - return literal({ + } + return { externalId: generateExternalId(this.context, userData), actionId: AdlibActionType.SELECT_FULL_GRAFIK, userData, @@ -143,11 +144,11 @@ export class PilotGraphicGenerator { currentPieceTags: [GetTagForFull(this.segmentExternalId, this.parsedCue.graphic.vcpid)], nextPieceTags: [GetTagForFullNext(this.segmentExternalId, this.parsedCue.graphic.vcpid)] } - }) + } } - public createPiece(): IBlueprintPiece { - return literal({ + public createPiece(): IBlueprintPiece { + return { externalId: this.partId, name: GraphicDisplayName(this.config, this.parsedCue), ...(IsTargetingFull(this.engine) || IsTargetingWall(this.engine) @@ -160,17 +161,17 @@ export class PilotGraphicGenerator { outputLayerId: this.getOutputLayer(), sourceLayerId: this.getSourceLayer(), prerollDuration: this.getPrerollDuration(), - lifespan: GetInfiniteModeForGraphic(this.engine, this.config, this.parsedCue), - metaData: literal({ + lifespan: GetPieceLifespanForGraphic(this.engine, this.config, this.parsedCue), + metaData: { sisyfosPersistMetaData: { sisyfosLayers: [] } - }), + }, content: this.createContent(), tags: IsTargetingFull(this.engine) ? [GetTagForFull(this.segmentExternalId, this.parsedCue.graphic.vcpid), TallyTags.FULL_IS_LIVE] : [] - }) + } } public createAdlibPiece(rank?: number): IBlueprintAdLibPiece { @@ -182,7 +183,7 @@ export class PilotGraphicGenerator { } } - public createFullDataStore(): IBlueprintPiece { + public createFullDataStore(): IBlueprintPiece { const content = this.createContent() content.timelineObjects = content.timelineObjects.filter( o => @@ -191,7 +192,7 @@ export class PilotGraphicGenerator { o.content.deviceType !== TSR.DeviceType.VIZMSE && o.content.deviceType !== TSR.DeviceType.CASPARCG ) - return literal({ + return { externalId: this.partId, name: GraphicDisplayName(this.config, this.parsedCue), enable: { @@ -201,19 +202,19 @@ export class PilotGraphicGenerator { sourceLayerId: SharedSourceLayers.SelectedAdlibGraphicsFull, lifespan: PieceLifespan.OutOnSegmentEnd, metaData: { - userData: literal({ + userData: { type: AdlibActionType.SELECT_FULL_GRAFIK, name: this.parsedCue.graphic.name, vcpid: this.parsedCue.graphic.vcpid, segmentExternalId: this.segmentExternalId - }), + }, sisyfosPersistMetaData: literal({ sisyfosLayers: [] }) }, content, tags: [GetTagForFullNext(this.segmentExternalId, this.parsedCue.graphic.vcpid)] - }) + } } private createContent(): WithTimeline { diff --git a/src/tv2-common/helpers/graphics/timing.ts b/src/tv2-common/helpers/graphics/timing.ts index 6b4668c17..3bfd74a9a 100644 --- a/src/tv2-common/helpers/graphics/timing.ts +++ b/src/tv2-common/helpers/graphics/timing.ts @@ -10,104 +10,82 @@ import { LifeSpan, PartDefinition, PartToParentClass, + TableConfigItemGFXTemplates, TV2BlueprintConfig } from 'tv2-common' -import { ControlClasses, GraphicEngine } from 'tv2-constants' +import { GraphicEngine } from 'tv2-constants' import { GetFullGraphicTemplateNameFromCue, IsTargetingTLF, IsTargetingWall } from '.' -export function GetInfiniteModeForGraphic( +export function GetPieceLifespanForGraphic( engine: GraphicEngine, config: TV2BlueprintConfig, - parsedCue: CueDefinitionGraphic, - isStickyIdent?: boolean + parsedCue: CueDefinitionGraphic ): PieceLifespan { - return IsTargetingWall(engine) - ? PieceLifespan.OutOnShowStyleEnd - : IsTargetingTLF(engine) - ? PieceLifespan.WithinPart - : isStickyIdent - ? PieceLifespan.OutOnSegmentEnd - : parsedCue.end && parsedCue.end.infiniteMode - ? LifeSpan(parsedCue.end.infiniteMode, PieceLifespan.WithinPart) - : FindInfiniteModeFromConfig(config, parsedCue) + if (IsTargetingWall(engine)) { + return PieceLifespan.OutOnShowStyleEnd + } + if (IsTargetingTLF(engine)) { + return PieceLifespan.WithinPart + } + if (parsedCue.end && parsedCue.end.infiniteMode) { + return LifeSpan(parsedCue.end.infiniteMode, PieceLifespan.WithinPart) + } + return FindInfiniteModeFromConfig(config, parsedCue) } export function FindInfiniteModeFromConfig( config: TV2BlueprintConfig, parsedCue: CueDefinitionGraphic ): PieceLifespan { - if (config.showStyle.GFXTemplates) { - const template = GetFullGraphicTemplateNameFromCue(config, parsedCue) - const iNewsName = GraphicIsInternal(parsedCue) ? parsedCue.graphic.template : undefined - const conf = config.showStyle.GFXTemplates.find(cnf => - cnf.VizTemplate - ? cnf.VizTemplate.toString().toUpperCase() === template.toUpperCase() && - (iNewsName ? cnf.INewsName.toUpperCase() === iNewsName.toUpperCase() : true) - : false - ) - - if (!conf) { - return PieceLifespan.WithinPart - } - - if (!conf.OutType || !conf.OutType.toString().length) { - return PieceLifespan.WithinPart - } + const template = GetFullGraphicTemplateNameFromCue(config, parsedCue) + const iNewsName = GraphicIsInternal(parsedCue) ? parsedCue.graphic.template : undefined + const conf = config.showStyle.GFXTemplates.find(cnf => + cnf.VizTemplate + ? cnf.VizTemplate.toString().toUpperCase() === template.toUpperCase() && + (iNewsName ? cnf.INewsName.toUpperCase() === iNewsName.toUpperCase() : true) + : false + ) + + if (!conf) { + return PieceLifespan.WithinPart + } - const type = conf.OutType.toString().toUpperCase() + if (!conf.OutType || !conf.OutType.toString().length) { + return PieceLifespan.WithinPart + } - if (type !== 'B' && type !== 'S' && type !== 'O') { - return PieceLifespan.WithinPart - } + const type = conf.OutType.toString().toUpperCase() - return LifeSpan(type, PieceLifespan.WithinPart) + if (type !== 'B' && type !== 'S' && type !== 'O') { + return PieceLifespan.WithinPart } - return PieceLifespan.WithinPart + return LifeSpan(type, PieceLifespan.WithinPart) } export function GetGraphicDuration( config: TV2BlueprintConfig, - cue: CueDefinitionGraphic, - defaultTime: boolean + cue: CueDefinitionGraphic ): number | undefined { if (config.showStyle.GFXTemplates) { - if (GraphicIsInternal(cue)) { - const template = config.showStyle.GFXTemplates.find(templ => - templ.INewsName ? templ.INewsName.toString().toUpperCase() === cue.graphic.template.toUpperCase() : false - ) - if (template) { - if (template.OutType && !template.OutType.toString().match(/default/i)) { - return undefined - } - } - } else if (GraphicIsPilot(cue)) { - const template = config.showStyle.GFXTemplates.find(templ => - templ.INewsName - ? templ.INewsName.toString().toUpperCase() === cue.graphic.vcpid.toString().toUpperCase() - : false - ) - if (template) { - if (template.OutType && !template.OutType.toString().match(/default/i)) { - return undefined - } - } + const template = findGFXTemplate(config, cue) + if (template && template.OutType && !template.OutType.toString().match(/default/i)) { + return undefined } } - return defaultTime ? GetDefaultOut(config) : undefined + return GetDefaultOut(config) } export function CreateTimingGraphic( config: TV2BlueprintConfig, - cue: CueDefinitionGraphic, - defaultTime: boolean = true + cue: CueDefinitionGraphic ): { start: number; duration?: number } { const ret: { start: number; duration?: number } = { start: 0, duration: 0 } const start = cue.start ? CalculateTime(cue.start) : 0 start !== undefined ? (ret.start = start) : (ret.start = 0) - const duration = GetGraphicDuration(config, cue, defaultTime) + const duration = GetGraphicDuration(config, cue) const end = cue.end ? cue.end.infiniteMode ? undefined @@ -126,11 +104,27 @@ export function GetEnableForWall(): TSR.TSRTimelineObj['enable'] { } } +export function findGFXTemplate( + config: TV2BlueprintConfig, + cue: CueDefinitionGraphic +): TableConfigItemGFXTemplates | undefined { + let graphicId: string | undefined + if (GraphicIsInternal(cue)) { + graphicId = cue.graphic.template + } else if (GraphicIsPilot(cue)) { + graphicId = cue.graphic.vcpid.toString() + } + if (graphicId === undefined) { + return undefined + } + return config.showStyle.GFXTemplates.find(templ => + templ.INewsName ? templ.INewsName.toString().toUpperCase() === graphicId?.toUpperCase() : false + ) +} export function GetEnableForGraphic( config: TV2BlueprintConfig, engine: GraphicEngine, cue: CueDefinitionGraphic, - isStickyIdent: boolean, partDefinition?: PartDefinition, adlib?: boolean ): TSR.TSRTimelineObj['enable'] { @@ -139,20 +133,13 @@ export function GetEnableForGraphic( } if ( - ((cue.end && cue.end.infiniteMode && cue.end.infiniteMode === 'B') || - GetInfiniteModeForGraphic(engine, config, cue, isStickyIdent) === PieceLifespan.OutOnSegmentEnd) && partDefinition && + (endsOnPartEnd(config, cue) || GetPieceLifespanForGraphic(engine, config, cue) === PieceLifespan.OutOnSegmentEnd) && !adlib ) { return { while: `.${PartToParentClass('studio0', partDefinition)} & !.adlib_deparent & !.full` } } - if (isStickyIdent) { - return { - while: `.${ControlClasses.ShowIdentGraphic} & !.full` - } - } - const timing = CreateTimingEnable(cue, GetDefaultOut(config)) if (!timing.lifespan) { @@ -169,3 +156,8 @@ export function GetEnableForGraphic( } } } +function endsOnPartEnd(config: TV2BlueprintConfig, cue: CueDefinitionGraphic) { + return ( + (cue.end && cue.end.infiniteMode && cue.end.infiniteMode === 'B') || findGFXTemplate(config, cue)?.OutType === 'B' + ) +} diff --git a/src/tv2-common/helpers/graphics/viz/index.ts b/src/tv2-common/helpers/graphics/viz/index.ts index 21138540f..973f952ac 100644 --- a/src/tv2-common/helpers/graphics/viz/index.ts +++ b/src/tv2-common/helpers/graphics/viz/index.ts @@ -1,10 +1,4 @@ -import { - GraphicsContent, - IBlueprintPiece, - IShowStyleUserContext, - TSR, - WithTimeline -} from '@tv2media/blueprints-integration' +import { GraphicsContent, IShowStyleUserContext, TSR, WithTimeline } from '@tv2media/blueprints-integration' import { Adlib, CueDefinitionGraphic, @@ -36,19 +30,18 @@ export function GetInternalGraphicContentVIZ( config: TV2BlueprintConfig, engine: GraphicEngine, parsedCue: CueDefinitionGraphic, - isIdentGraphic: boolean, partDefinition: PartDefinition | undefined, mappedTemplate: string, adlib: boolean -): IBlueprintPiece['content'] { - return literal>({ +): WithTimeline { + return { fileName: parsedCue.graphic.template, path: parsedCue.graphic.template, ignoreMediaObjectStatus: true, timelineObjects: literal([ literal({ id: '', - enable: GetEnableForGraphic(config, engine, parsedCue, isIdentGraphic, partDefinition, adlib), + enable: GetEnableForGraphic(config, engine, parsedCue, partDefinition, adlib), priority: 1, layer: GetTimelineLayerForGraphic(config, GetFullGraphicTemplateNameFromCue(config, parsedCue)), content: { @@ -63,7 +56,7 @@ export function GetInternalGraphicContentVIZ( // Assume DSK is off by default (config table) ...EnableDSK(config, 'OVL') ]) - }) + } } export function GetPilotGraphicContentViz( @@ -74,7 +67,7 @@ export function GetPilotGraphicContentViz( engine: GraphicEngine, adlib?: Adlib ): WithTimeline { - return literal>({ + return { fileName: 'PILOT_' + parsedCue.graphic.vcpid.toString(), path: parsedCue.graphic.vcpid.toString(), timelineObjects: [ @@ -82,7 +75,7 @@ export function GetPilotGraphicContentViz( id: '', enable: IsTargetingOVL(engine) || IsTargetingWall(engine) - ? GetEnableForGraphic(config, engine, parsedCue, false, undefined, !!adlib) + ? GetEnableForGraphic(config, engine, parsedCue, undefined, !!adlib) : { start: 0 }, @@ -113,5 +106,5 @@ export function GetPilotGraphicContentViz( }), ...(IsTargetingFull(engine) ? settings.createPilotTimelineForStudio(config, context, !!adlib) : []) ] - }) + } } diff --git a/src/tv2-common/helpers/rundownAdLibActions.ts b/src/tv2-common/helpers/rundownAdLibActions.ts index 46243960a..05402989d 100644 --- a/src/tv2-common/helpers/rundownAdLibActions.ts +++ b/src/tv2-common/helpers/rundownAdLibActions.ts @@ -25,11 +25,11 @@ export function GetTransitionAdLibActions< if (config.showStyle.ShowstyleTransition && config.showStyle.ShowstyleTransition.length) { const defaultTransition = config.showStyle.ShowstyleTransition - const userData = literal({ + const userData: ActionTakeWithTransition = { type: AdlibActionType.TAKE_WITH_TRANSITION, variant: ParseTransitionString(defaultTransition), takeNow: true - }) + } const jingleConfig = config.showStyle.BreakerConfig.find( j => j.BreakerName === config.showStyle.ShowstyleTransition @@ -63,11 +63,11 @@ export function GetTransitionAdLibActions< if (config.showStyle.Transitions) { config.showStyle.Transitions.forEach((transition, i) => { if (transition.Transition && transition.Transition.length) { - const userData = literal({ + const userData: ActionTakeWithTransition = { type: AdlibActionType.TAKE_WITH_TRANSITION, variant: ParseTransitionString(transition.Transition), takeNow: true - }) + } const jingleConfig = config.showStyle.BreakerConfig.find(j => j.BreakerName === transition.Transition) let alphaAtStart: number | undefined @@ -141,7 +141,7 @@ function makeTransitionAction( const tag = GetTagForTransition(userData.variant) const isEffekt = !!label.match(/^\d+$/) - return literal({ + return { externalId: `${JSON.stringify(userData)}_${AdlibActionType.TAKE_WITH_TRANSITION}_${rank}`, actionId: AdlibActionType.TAKE_WITH_TRANSITION, userData, @@ -159,5 +159,5 @@ function makeTransitionAction( ? {} : CreateJingleExpectedMedia(config, jingle, alphaAtStart ?? 0, duration ?? 0, alphaAtEnd ?? 0) } - }) + } } diff --git a/src/tv2-common/helpers/serverResume.ts b/src/tv2-common/helpers/serverResume.ts index 7fae49cfc..28d6bb96b 100644 --- a/src/tv2-common/helpers/serverResume.ts +++ b/src/tv2-common/helpers/serverResume.ts @@ -5,7 +5,7 @@ import { IBlueprintResolvedPieceInstance, VTContent } from '@tv2media/blueprints-integration' -import { PartEndStateExt, t } from 'tv2-common' +import { PartEndStateExt, PieceMetaData, t } from 'tv2-common' import { SharedSourceLayers } from 'tv2-constants' import _ = require('underscore') import { DVEPieceMetaData } from '../content' @@ -61,7 +61,11 @@ export async function getServerPosition( ? context.getCurrentTime() + replacingCurrentPieceWithOffset : undefined - return getServerPositionForPartInstance(partInstance, await context.getResolvedPieceInstances('current'), pieceEnd) + const pieceInstances = (await context.getResolvedPieceInstances('current')) as Array< + IBlueprintResolvedPieceInstance + > + + return getServerPositionForPartInstance(partInstance, pieceInstances, pieceEnd) } /** @@ -69,7 +73,7 @@ export async function getServerPosition( */ export function getServerPositionForPartInstance( partInstance: IBlueprintPartInstance, - pieceInstances: IBlueprintResolvedPieceInstance[], + pieceInstances: Array>, currentPieceEnd?: number ): ServerPosition | undefined { currentPieceEnd = @@ -102,7 +106,7 @@ export function getServerPositionForPartInstance( ) } else if (pieceInstance.piece.sourceLayerId === SharedSourceLayers.PgmDVEAdLib) { updateServerPositionFromDVEPiece( - pieceInstance, + pieceInstance as IBlueprintResolvedPieceInstance, partInstance, pieceDuration, currentPieceEnd, @@ -119,7 +123,7 @@ export function getServerPositionForPartInstance( function updateServerPositionFromTransition( partInstance: IBlueprintPartInstance, currentServerPosition: ServerPosition | undefined, - currentPiecesWithServer: Array>, + currentPiecesWithServer: Array>, previousPartEndState: Partial | undefined ) { const inTransitionDuration = partInstance.part.inTransition?.previousPartKeepaliveDuration @@ -134,13 +138,13 @@ function updateServerPositionFromTransition( } function updateServerPositionFromDVEPiece( - pieceInstance: IBlueprintResolvedPieceInstance, + pieceInstance: IBlueprintResolvedPieceInstance, partInstance: IBlueprintPartInstance, pieceDuration: number | undefined, currentPieceEnd: number | undefined, currentServerPosition: ServerPosition | undefined ) { - const serverPlaybackTiming = (pieceInstance.piece.metaData as DVEPieceMetaData | undefined)?.serverPlaybackTiming + const serverPlaybackTiming = pieceInstance.piece.metaData?.serverPlaybackTiming if (serverPlaybackTiming) { for (const timing of serverPlaybackTiming) { const start = getStartTimeForServerInDVE(timing, partInstance, pieceInstance) @@ -156,7 +160,7 @@ function updateServerPositionFromDVEPiece( } function getStartTimeForServerInDVE( - timing: { start?: number | undefined; end?: number | undefined }, + timing: { start?: number; end?: number }, partInstance: IBlueprintPartInstance, pieceInstance: IBlueprintResolvedPieceInstance ) { @@ -167,7 +171,7 @@ function getStartTimeForServerInDVE( } function getEndTimeForServerInDVE( - timing: { start?: number | undefined; end?: number | undefined }, + timing: { start?: number; end?: number }, pieceDuration: number | undefined, partInstance: IBlueprintPartInstance, pieceInstance: IBlueprintResolvedPieceInstance diff --git a/src/tv2-common/hotkeys/hotkey-defaults.ts b/src/tv2-common/hotkeys/hotkey-defaults.ts index 04566937e..e6da72e03 100644 --- a/src/tv2-common/hotkeys/hotkey-defaults.ts +++ b/src/tv2-common/hotkeys/hotkey-defaults.ts @@ -36,7 +36,6 @@ export const defaultHotkeys: TV2Hotkeys = { { sourceLayers: [ SharedSourceLayers.PgmGraphicsIdent, - SharedSourceLayers.PgmGraphicsIdentPersistent, SharedSourceLayers.PgmGraphicsTop, SharedSourceLayers.PgmGraphicsLower, SharedSourceLayers.PgmGraphicsHeadline, @@ -48,7 +47,7 @@ export const defaultHotkeys: TV2Hotkeys = { name: 'overlay ALT UD' }, { - sourceLayers: [SharedSourceLayers.PgmGraphicsIdent, SharedSourceLayers.PgmGraphicsIdentPersistent], + sourceLayers: [SharedSourceLayers.PgmGraphicsIdent], key: 'Ctrl+Shift+KeyA', name: 'ovl: ident OUT' }, diff --git a/src/tv2-common/inewsConversion/converters/ParseBody.ts b/src/tv2-common/inewsConversion/converters/ParseBody.ts index 2a2e3bf08..8e14270a8 100644 --- a/src/tv2-common/inewsConversion/converters/ParseBody.ts +++ b/src/tv2-common/inewsConversion/converters/ParseBody.ts @@ -192,7 +192,13 @@ export function ParseBody( // Handle intro segments, they have special behaviour. if (segmentName === 'INTRO') { - ;((definition as unknown) as PartDefinitionIntro).type = PartType.INTRO + definition = { + ...definition, + type: PartType.INTRO, + rawType: 'INTRO', + externalId: `${segmentId}-${definitions.length}`, + segmentExternalId: segmentId + } cues.forEach(cue => { if (cue !== null) { const parsedCue = ParseCue(cue, config) @@ -202,9 +208,6 @@ export function ParseBody( } } }) - definition.rawType = 'INTRO' - definition.externalId = `${segmentId}-${definitions.length}` - definition.segmentExternalId = segmentId definitions.push(definition) definition = initDefinition(fields, modified, segmentName) return definitions diff --git a/src/tv2-common/inewsConversion/converters/ParseCue.ts b/src/tv2-common/inewsConversion/converters/ParseCue.ts index 14a6709bf..fa52631e8 100644 --- a/src/tv2-common/inewsConversion/converters/ParseCue.ts +++ b/src/tv2-common/inewsConversion/converters/ParseCue.ts @@ -1,4 +1,4 @@ -import { GetInfiniteModeForGraphic, literal, TableConfigSchema, TV2BlueprintConfig, UnparsedCue } from 'tv2-common' +import { GetPieceLifespanForGraphic, literal, TableConfigSchema, TV2BlueprintConfig, UnparsedCue } from 'tv2-common' import { CueType, GraphicEngine, PartType, SourceType } from 'tv2-constants' import { getSourceDefinition, @@ -578,13 +578,13 @@ function parseAdLib(cue: string[]) { } // tslint:disable-next-line: prefer-for-of - for (let i = 0; i < cue.length; i++) { - const input = cue[i].match(/^(INP\d)+=(.+)$/i) + for (const element of cue) { + const input = element.match(/^(INP\d)+=(.+)$/i) if (input && input[1] && input[2] && adlib.inputs !== undefined) { adlib.inputs[input[1].toUpperCase() as keyof DVESources] = getSourceDefinition(input[2]) } - const bynavn = cue[i].match(/^BYNAVN=(.+)$/i) + const bynavn = element.match(/^BYNAVN=(.+)$/i) if (bynavn) { adlib.bynavn = bynavn[1].split(/\/|\\/i) } @@ -996,17 +996,10 @@ export function AddParentClass(config: TV2BlueprintConfig, partDefinition: PartD } return partDefinition.cues.some( - c => - c.type === CueType.Graphic && - GraphicIsInternal(c) && - GetInfiniteModeForGraphic(c.target, config, c, IsStickyIdent(c)) + c => c.type === CueType.Graphic && GraphicIsInternal(c) && GetPieceLifespanForGraphic(c.target, config, c) ) } -export function IsStickyIdent(cue: CueDefinitionGraphic) { - return !!cue.graphic.template.match(/direkte/i) -} - export function UnpairedPilotToGraphic( pilotCue: CueDefinitionUnpairedPilot, target: GraphicEngine, diff --git a/src/tv2-common/inewsConversion/converters/__tests__/cue-parser.spec.ts b/src/tv2-common/inewsConversion/converters/__tests__/cue-parser.spec.ts index d591ec062..385fa803d 100644 --- a/src/tv2-common/inewsConversion/converters/__tests__/cue-parser.spec.ts +++ b/src/tv2-common/inewsConversion/converters/__tests__/cue-parser.spec.ts @@ -360,26 +360,6 @@ describe('Cue parser', () => { ) }) - test('Grafik (kg) - Inline first text field, blank time', () => { - const cueGrafik = ['kg bund TEXT MORETEXT', 'some@email.fakeTLD', ';x.xx'] - const result = ParseCue(cueGrafik, config) - expect(result).toEqual( - literal>({ - type: CueType.Graphic, - target: 'OVL', - - graphic: { - type: 'internal', - template: 'bund', - cue: 'kg', - textFields: ['TEXT MORETEXT', 'some@email.fakeTLD'] - }, - adlib: true, - iNewsCommand: 'kg' - }) - ) - }) - test('Grafik (kg) - Multiline text fields', () => { const cueGrafik = ['kg bund', 'TEXT MORETEXT', 'some@email.fakeTLD', ';0.02'] const result = ParseCue(cueGrafik, config) diff --git a/src/tv2-common/layers/sourceLayers.ts b/src/tv2-common/layers/sourceLayers.ts index f4746d8f0..e52a0b919 100644 --- a/src/tv2-common/layers/sourceLayers.ts +++ b/src/tv2-common/layers/sourceLayers.ts @@ -1,7 +1,6 @@ import { ISourceLayer, SourceLayerType } from '@tv2media/blueprints-integration' import { ATEMModel } from '../../types/atem' import { GetDSKCount } from '../helpers' -import { literal } from '../util' /** * Get the sourcelayer name for a given DSK. @@ -12,7 +11,7 @@ export function SourceLayerAtemDSK(i: number): string { } function GetSourceLayerDefaultsForDSK(i: number): ISourceLayer { - return literal({ + return { _id: SourceLayerAtemDSK(i), _rank: 22, name: `DSK${i + 1} off`, @@ -27,7 +26,7 @@ function GetSourceLayerDefaultsForDSK(i: number): ISourceLayer { isHidden: true, allowDisable: false, onPresenterScreen: false - }) + } } export function GetDSKSourceLayerNames(atemModel: ATEMModel): string[] { diff --git a/src/tv2-common/migrations/addKeepAudio.ts b/src/tv2-common/migrations/addKeepAudio.ts index 18dcdc472..c6629842c 100644 --- a/src/tv2-common/migrations/addKeepAudio.ts +++ b/src/tv2-common/migrations/addKeepAudio.ts @@ -1,9 +1,8 @@ import { MigrationContextStudio, MigrationStepStudio, TableConfigItemValue } from '@tv2media/blueprints-integration' import * as _ from 'underscore' -import { literal } from '../util' export function AddKeepAudio(versionStr: string, configName: string): MigrationStepStudio { - const res = literal({ + const res: MigrationStepStudio = { id: `${versionStr}.studioConfig.addKeepAudio.${configName}`, version: versionStr, canBeRunAutomatically: true, @@ -29,7 +28,7 @@ export function AddKeepAudio(versionStr: string, configName: string): MigrationS context.setConfig(configName, configVal) } } - }) + } return res } diff --git a/src/tv2-common/migrations/forceSourceLayerToDefaultsBase.ts b/src/tv2-common/migrations/forceSourceLayerToDefaultsBase.ts index d94d7012f..137fad578 100644 --- a/src/tv2-common/migrations/forceSourceLayerToDefaultsBase.ts +++ b/src/tv2-common/migrations/forceSourceLayerToDefaultsBase.ts @@ -1,5 +1,4 @@ import { ISourceLayer, MigrationContextShowStyle, MigrationStepShowStyle } from '@tv2media/blueprints-integration' -import { literal } from 'tv2-common' import _ = require('underscore') export function forceSourceLayerToDefaultsBase( @@ -9,7 +8,7 @@ export function forceSourceLayerToDefaultsBase( layer: string, overrideSteps?: string[] ): MigrationStepShowStyle { - return literal({ + return { id: `${versionStr}.${showStyleId}.sourcelayer.defaults.${layer}.forced`, version: versionStr, canBeRunAutomatically: true, @@ -43,5 +42,5 @@ export function forceSourceLayerToDefaultsBase( context.insertSourceLayer(layer, defaultVal) } } - }) + } } diff --git a/src/tv2-common/migrations/hotkeys.ts b/src/tv2-common/migrations/hotkeys.ts index 1d1ff0fa7..de3283127 100644 --- a/src/tv2-common/migrations/hotkeys.ts +++ b/src/tv2-common/migrations/hotkeys.ts @@ -43,7 +43,7 @@ export function GetDefaultAdLibTriggers( sourceLayers ) - const needsMigration = shortcutsDefaults.some(defaultShortcut => { + return shortcutsDefaults.some(defaultShortcut => { const existingShortcut = context.getTriggeredAction(defaultShortcut._id) if (!existingShortcut) { @@ -52,7 +52,6 @@ export function GetDefaultAdLibTriggers( return forceToDefaults && shortcutsAreDifferent(defaultShortcut, existingShortcut) }) - return needsMigration }, migrate: (context: MigrationContextShowStyle) => { const shortcutsDefaults = MakeAllAdLibsTriggers( @@ -79,7 +78,7 @@ export function RemoveOldShortcuts( showStyleId: string, sourceLayerDefaults: ISourceLayer[] ): MigrationStepShowStyle { - return literal({ + return { id: `${versionStr}.migrateShortcutsToAdLibTriggers.${showStyleId}`, version: versionStr, canBeRunAutomatically: true, @@ -88,15 +87,13 @@ export function RemoveOldShortcuts( ISourceLayerWithHotKeys | undefined > - const oldHotKeysExist = sourceLayers.some( + return sourceLayers.some( sourceLayer => !!sourceLayer?.clearKeyboardHotkey || !!sourceLayer?.activateKeyboardHotkeys || !!sourceLayer?.activateStickyKeyboardHotkey || sourceLayer?.assignHotkeysToGlobalAdlibs !== undefined ) - - return oldHotKeysExist }, migrate: (context: MigrationContextShowStyle) => { for (const sourceLayer of sourceLayerDefaults) { @@ -113,5 +110,5 @@ export function RemoveOldShortcuts( context.updateSourceLayer(sourceLayer._id, coreSourceLayer) } } - }) + } } diff --git a/src/tv2-common/migrations/index.ts b/src/tv2-common/migrations/index.ts index c74ecaa72..33e1da474 100644 --- a/src/tv2-common/migrations/index.ts +++ b/src/tv2-common/migrations/index.ts @@ -22,7 +22,7 @@ export * from './forceSourceLayerToDefaultsBase' export * from './hotkeys' export function RenameStudioConfig(versionStr: string, studio: string, from: string, to: string): MigrationStepStudio { - return literal({ + return { id: `${versionStr}.studioConfig.rename.${from}.${studio}`, version: versionStr, canBeRunAutomatically: true, @@ -41,7 +41,7 @@ export function RenameStudioConfig(versionStr: string, studio: string, from: str context.removeConfig(from) } - }) + } } export function renameSourceLayer( @@ -50,7 +50,7 @@ export function renameSourceLayer( from: string, to: string ): MigrationStepShowStyle { - return literal({ + return { id: `${versionStr}.renameSourceLayer.${studioId}.${from}.${to}`, version: versionStr, canBeRunAutomatically: true, @@ -69,10 +69,10 @@ export function renameSourceLayer( context.insertSourceLayer(to, existing) context.removeSourceLayer(from) } - }) + } } -export function removeSourceLayer(versionStr: string, studioId: string, layer: string) { +export function removeSourceLayer(versionStr: string, studioId: string, layer: string): MigrationStepShowStyle { return literal({ id: `${versionStr}.removeSourceLayer.${studioId}.${layer}`, version: versionStr, @@ -94,8 +94,12 @@ export function removeSourceLayer(versionStr: string, studioId: string, layer: s }) } -export function AddGraphicToGFXTable(versionStr: string, studio: string, config: TableConfigItemGFXTemplates) { - return literal({ +export function AddGraphicToGFXTable( + versionStr: string, + studio: string, + config: TableConfigItemGFXTemplates +): MigrationStepShowStyle { + return { id: `${versionStr}.gfxConfig.add${config.INewsName}.${studio}`, version: versionStr, canBeRunAutomatically: true, @@ -118,7 +122,7 @@ export function AddGraphicToGFXTable(versionStr: string, studio: string, config: context.setBaseConfig('GFXTemplates', (existing as unknown) as ConfigItemValue) } - }) + } } export function addSourceToSourcesConfig( @@ -126,8 +130,8 @@ export function addSourceToSourcesConfig( studio: string, configId: string, source: TableConfigItemSourceMappingWithSisyfos -) { - return literal({ +): MigrationStepStudio { + return { id: `${versionStr}.studioConfig.addReplaySource.${source.SourceName}.${studio}`, version: versionStr, canBeRunAutomatically: true, @@ -144,7 +148,7 @@ export function addSourceToSourcesConfig( config.push(source) context.setConfig(configId, (config as unknown) as ConfigItemValue) } - }) + } } export function changeGFXTemplate( @@ -152,9 +156,9 @@ export function changeGFXTemplate( studio: string, oldConfig: Partial, config: Partial -) { +): MigrationStepShowStyle { const keysToUpdate = Object.keys(config).join('_') - return literal({ + return { id: `${versionStr}.gfxConfig.change_${keysToUpdate}.${studio}`, version: versionStr, canBeRunAutomatically: true, @@ -176,7 +180,7 @@ export function changeGFXTemplate( context.setBaseConfig('GFXTemplates', (existing as unknown) as ConfigItemValue) } - }) + } } function isGfxTemplateSubset( @@ -194,40 +198,38 @@ export function SetLayerNamesToDefaults( const migrations: MigrationStepStudio[] = [] for (const [layerId, mapping] of Object.entries(mappings)) { - migrations.push( - literal({ - id: `${versionStr}.studioConfig.setLayerName.${layerId}.${studio}`, - version: versionStr, - canBeRunAutomatically: true, - validate: (context: MigrationContextStudio) => { - const configVal = context.getMapping(layerId) - - if (!configVal) { - return false - } - - return configVal.layerName !== mapping.layerName - }, - migrate: (context: MigrationContextStudio) => { - const configVal = context.getMapping(layerId) + migrations.push({ + id: `${versionStr}.studioConfig.setLayerName.${layerId}.${studio}`, + version: versionStr, + canBeRunAutomatically: true, + validate: (context: MigrationContextStudio) => { + const configVal = context.getMapping(layerId) + + if (!configVal) { + return false + } - if (!configVal) { - return - } + return configVal.layerName !== mapping.layerName + }, + migrate: (context: MigrationContextStudio) => { + const configVal = context.getMapping(layerId) - configVal.layerName = mapping.layerName - context.removeMapping(layerId) - context.insertMapping(layerId, configVal) + if (!configVal) { + return } - }) - ) + + configVal.layerName = mapping.layerName + context.removeMapping(layerId) + context.insertMapping(layerId, configVal) + } + }) } return migrations } -export function SetConfigTo(versionStr: string, studio: string, id: string, value: any) { - return literal({ +export function SetConfigTo(versionStr: string, studio: string, id: string, value: any): MigrationStepStudio { + return { id: `${versionStr}.config.valueSet.${studio}.${id}`, version: versionStr, canBeRunAutomatically: true, @@ -244,11 +246,11 @@ export function SetConfigTo(versionStr: string, studio: string, id: string, valu migrate: (context: MigrationContextStudio) => { context.setConfig(id, value) } - }) + } } -export function RemoveConfig(versionStr: string, studio: string, id: string) { - return literal({ +export function RemoveConfig(versionStr: string, studio: string, id: string): MigrationStepStudio { + return { id: `${versionStr}.config.valueSet.${studio}.${id}`, version: versionStr, canBeRunAutomatically: true, @@ -258,7 +260,7 @@ export function RemoveConfig(versionStr: string, studio: string, id: string) { migrate: (context: MigrationContextStudio) => { context.removeConfig(id) } - }) + } } const SOUNDBED_REGEX = /^audio\/(.*)/i @@ -288,7 +290,7 @@ export function StripFolderFromShowStyleConfig( configFields: string[], regex: RegExp ): MigrationStepShowStyle { - return literal({ + return { id: `${versionStr}.normalizeFolders.${studio}.${configId}`, version: versionStr, canBeRunAutomatically: true, @@ -330,7 +332,7 @@ export function StripFolderFromShowStyleConfig( context.setBaseConfig(configId, configTableValue) } - }) + } } export function PrefixEvsWithEvs( @@ -339,7 +341,7 @@ export function PrefixEvsWithEvs( configId: string, evsSourceNumber: string ): MigrationStepStudio { - return literal({ + return { id: `${versionStr}.prefixEvs${evsSourceNumber}WithEvs.${studio}`, version: versionStr, canBeRunAutomatically: true, @@ -364,5 +366,5 @@ export function PrefixEvsWithEvs( config[index] = evsSource context.setConfig(configId, (config as unknown) as ConfigItemValue) } - }) + } } diff --git a/src/tv2-common/migrations/moveSourcesToTable.ts b/src/tv2-common/migrations/moveSourcesToTable.ts index 9533835cb..bc8c5cd49 100644 --- a/src/tv2-common/migrations/moveSourcesToTable.ts +++ b/src/tv2-common/migrations/moveSourcesToTable.ts @@ -10,7 +10,7 @@ export function MoveSourcesToTable( getSisyfosLayersForMigration: (configName: string, val: string) => string[], studioMics?: boolean ): MigrationStepStudio { - const res = literal({ + return { id: `${versionStr}.studioConfig.moveToTable.${configName}`, version: versionStr, canBeRunAutomatically: true, @@ -52,13 +52,11 @@ export function MoveSourcesToTable( context.setConfig(configName, table) } } - }) - - return res + } } export function MoveClipSourcePath(versionStr: string, studio: string): MigrationStepStudio { - const res = literal({ + return { id: `${versionStr}.studioConfig.moveClipSourcePath.${studio}`, version: versionStr, canBeRunAutomatically: true, @@ -76,7 +74,5 @@ export function MoveClipSourcePath(versionStr: string, studio: string): Migratio context.removeConfig('ClipSourcePath') } } - }) - - return res + } } diff --git a/src/tv2-common/migrations/sourceManifest.ts b/src/tv2-common/migrations/sourceManifest.ts index 548259eac..3d180ebaa 100644 --- a/src/tv2-common/migrations/sourceManifest.ts +++ b/src/tv2-common/migrations/sourceManifest.ts @@ -8,7 +8,7 @@ export function MakeConfigForSources( acceptPersistAudio: boolean, defaultVal: ConfigManifestEntryTable['defaultVal'] ): ConfigManifestEntryTable { - return literal({ + return { id: `Sources${name}`, name: `${displayName} Mapping`, description: `${displayName} number to ATEM input and Sisyfos layer`, @@ -85,5 +85,5 @@ export function MakeConfigForSources( ] : []) ] - }) + } } diff --git a/src/tv2-common/migrations/transitions.ts b/src/tv2-common/migrations/transitions.ts index e7abce264..c6e7e353b 100644 --- a/src/tv2-common/migrations/transitions.ts +++ b/src/tv2-common/migrations/transitions.ts @@ -3,7 +3,7 @@ import { literal } from 'tv2-common' import { TableConfigItemAdLibTransitions } from '../blueprintConfig' export function SetShowstyleTransitionMigrationStep(versionStr: string, newValue: string): MigrationStepShowStyle { - return literal({ + return { id: `${versionStr}.setShowstyleTransition`, version: versionStr, canBeRunAutomatically: true, @@ -19,7 +19,7 @@ export function SetShowstyleTransitionMigrationStep(versionStr: string, newValue migrate: (context: MigrationContextShowStyle) => { context.setBaseConfig('ShowstyleTransition', newValue) } - }) + } } type TransitionsTableValue = TableConfigItemAdLibTransitions & { _id: string; [key: string]: string } @@ -31,49 +31,47 @@ export function UpsertValuesIntoTransitionTable( const steps: MigrationStepShowStyle[] = [] values.forEach(val => { - steps.push( - literal({ - id: `${versionStr}.insertTransition.${val.Transition.replace(/[\s\W]/g, '_')}`, - version: versionStr, - canBeRunAutomatically: true, - validate: (context: MigrationContextShowStyle) => { - const table = (context.getBaseConfig('Transitions') as unknown) as TransitionsTableValue[] | undefined + steps.push({ + id: `${versionStr}.insertTransition.${val.Transition.replace(/[\s\W]/g, '_')}`, + version: versionStr, + canBeRunAutomatically: true, + validate: (context: MigrationContextShowStyle) => { + const table = (context.getBaseConfig('Transitions') as unknown) as TransitionsTableValue[] | undefined - if (!table) { - return `Transitions table does not exists` - } + if (!table) { + return `Transitions table does not exists` + } - const existingVal = table.find(v => v.Transition === val.Transition) + const existingVal = table.find(v => v.Transition === val.Transition) - if (!existingVal) { - return `Transition "${val.Transition}" does not exist` - } + if (!existingVal) { + return `Transition "${val.Transition}" does not exist` + } - return existingVal.Transition !== val.Transition - }, - migrate: (context: MigrationContextShowStyle) => { - const table = (context.getBaseConfig('Transitions') as unknown) as TransitionsTableValue[] | undefined + return existingVal.Transition !== val.Transition + }, + migrate: (context: MigrationContextShowStyle) => { + const table = (context.getBaseConfig('Transitions') as unknown) as TransitionsTableValue[] | undefined - if (!table) { - context.setBaseConfig('Transitions', [ - literal({ - _id: val.Transition.replace(/\W\s/g, '_'), - Transition: val.Transition - }) - ]) - } else { - table.push( - literal({ - _id: val.Transition.replace(/\W\s/g, '_'), - Transition: val.Transition - }) - ) + if (!table) { + context.setBaseConfig('Transitions', [ + literal({ + _id: val.Transition.replace(/\W\s/g, '_'), + Transition: val.Transition + }) + ]) + } else { + table.push( + literal({ + _id: val.Transition.replace(/\W\s/g, '_'), + Transition: val.Transition + }) + ) - context.setBaseConfig('Transitions', table) - } + context.setBaseConfig('Transitions', table) } - }) - ) + } + }) }) return steps diff --git a/src/tv2-common/onTimelineGenerate.ts b/src/tv2-common/onTimelineGenerate.ts index eecdef434..9d6fe0a8b 100644 --- a/src/tv2-common/onTimelineGenerate.ts +++ b/src/tv2-common/onTimelineGenerate.ts @@ -12,7 +12,7 @@ import { TimelinePersistentState, TSR } from '@tv2media/blueprints-integration' -import { CasparPlayerClip, literal } from 'tv2-common' +import { ActionSelectFullGrafik, ActionSelectJingle, ActionSelectServerClip, CasparPlayerClip } from 'tv2-common' import { AbstractLLayer, TallyTags } from 'tv2-constants' import * as _ from 'underscore' import { SisyfosLLAyer } from '../tv2_afvd_studio/layers' @@ -58,6 +58,22 @@ export interface PieceMetaData { modifiedByAction?: boolean } +export interface GraphicPieceMetaData extends PieceMetaData { + belongsToRemotePart?: boolean +} + +export interface JinglePieceMetaData extends PieceMetaData { + userData: ActionSelectJingle +} + +export interface FullPieceMetaData extends PieceMetaData { + userData: ActionSelectFullGrafik +} + +export interface ServerPieceMetaData extends PieceMetaData { + userData: ActionSelectServerClip +} + export interface SisyfosPersistMetaData { sisyfosLayers: string[] wantsToPersistAudio?: boolean @@ -80,7 +96,7 @@ export function onTimelineGenerate< timeline: OnGenerateTimelineObj[], previousPersistentState: TimelinePersistentState | undefined, previousPartEndState: PartEndState | undefined, - resolvedPieces: IBlueprintResolvedPieceInstance[], + resolvedPieces: Array>, getConfig: (context: IShowStyleContext) => ShowStyleConfig, sourceLayers: ABSourceLayers, _casparLayerClipPending: string, @@ -144,9 +160,7 @@ function processServerLookaheads( return ( [sourceLayers.Caspar.ClipPending, CasparPlayerClip(1), CasparPlayerClip(2)].includes(layer) && !obj.isLookahead && - resolvedPieces.some( - p => p._id === obj.pieceInstanceId && (p as any).partInstanceId === context.currentPartInstance?._id - ) + resolvedPieces.some(p => p._id === obj.pieceInstanceId && p.partInstanceId === context.currentPartInstance?._id) ) }) @@ -189,12 +203,14 @@ function processServerLookaheads( }) } -function isAnyPieceInjectedIntoPart(resolvedPieces: IBlueprintResolvedPieceInstance[], context: ITimelineEventContext) { +function isAnyPieceInjectedIntoPart( + resolvedPieces: Array>, + context: ITimelineEventContext +) { return resolvedPieces .filter(piece => piece.partInstanceId === context.currentPartInstance?._id) .some(piece => { - const metaData = piece.piece.metaData as PieceMetaData | undefined - return metaData?.sisyfosPersistMetaData?.isPieceInjectedInPart + return piece.piece.metaData?.sisyfosPersistMetaData?.isPieceInjectedInPart }) } @@ -202,7 +218,7 @@ export function getEndStateForPart( _context: IRundownContext, _previousPersistentState: TimelinePersistentState | undefined, partInstance: IBlueprintPartInstance, - resolvedPieces: IBlueprintResolvedPieceInstance[], + resolvedPieces: Array>, time: number ): PartEndState { const endState: PartEndStateExt = { @@ -219,8 +235,8 @@ export function getEndStateForPart( p => _.isNumber(p.piece.enable.start) && p.piece.enable && - (p.piece.enable.start as number) <= time && - (!p.piece.enable.duration || p.piece.enable.start + (p.piece.enable.duration as number) >= time) + p.piece.enable.start <= time && + (!p.piece.enable.duration || p.piece.enable.start + p.piece.enable.duration >= time) ) const previousPersistentState: TimelinePersistentStateExt = _previousPersistentState as TimelinePersistentStateExt @@ -233,7 +249,7 @@ export function getEndStateForPart( for (const piece of activePieces) { if (piece.piece.metaData) { - const meta = (piece.piece.metaData as PieceMetaData).mediaPlayerSessions + const meta = piece.piece.metaData.mediaPlayerSessions if (meta && meta.length) { endState.mediaPlayerSessions[piece.piece.sourceLayerId] = meta } @@ -277,11 +293,11 @@ function dveBoxLookaheadUseOriginalEnable(timeline: OnGenerateTimelineObj[]) { } export function createSisyfosPersistedLevelsTimelineObject( - resolvedPieces: IBlueprintResolvedPieceInstance[], + resolvedPieces: Array>, previousSisyfosLayersThatWantsToBePersisted: SisyfosPersistMetaData['sisyfosLayers'] ): TSR.TimelineObjSisyfosChannels { const layersToPersist = findLayersToPersist(resolvedPieces, previousSisyfosLayersThatWantsToBePersisted) - return literal({ + return { id: 'sisyfosPersistenceObject', enable: { start: 0 @@ -298,25 +314,22 @@ export function createSisyfosPersistedLevelsTimelineObject( } }) } - }) + } } function findLayersToPersist( - pieces: IBlueprintResolvedPieceInstance[], + pieces: Array>, sisyfosLayersThatWantsToBePersisted: string[] ): string[] { const sortedPieces = pieces - .filter(piece => { - const metaData = piece.piece.metaData as PieceMetaData | undefined - return metaData?.sisyfosPersistMetaData - }) + .filter(piece => piece.piece.metaData?.sisyfosPersistMetaData) .sort((a, b) => b.resolvedStart - a.resolvedStart) if (sortedPieces.length === 0) { return [] } - const firstPieceMetaData = sortedPieces[0].piece.metaData as PieceMetaData + const firstPieceMetaData = sortedPieces[0].piece.metaData! if (!firstPieceMetaData.sisyfosPersistMetaData!.acceptPersistAudio) { return firstPieceMetaData.sisyfosPersistMetaData!.wantsToPersistAudio ? firstPieceMetaData.sisyfosPersistMetaData!.sisyfosLayers @@ -325,8 +338,8 @@ function findLayersToPersist( const layersToPersist: string[] = [] for (let i = 0; i < sortedPieces.length; i++) { - const pieceMetaData = sortedPieces[i].piece.metaData as PieceMetaData - const sisyfosPersistMetaData: SisyfosPersistMetaData = pieceMetaData!.sisyfosPersistMetaData! + const pieceMetaData = sortedPieces[i].piece.metaData! + const sisyfosPersistMetaData: SisyfosPersistMetaData = pieceMetaData.sisyfosPersistMetaData! if (sisyfosPersistMetaData.wantsToPersistAudio) { layersToPersist.push(...sisyfosPersistMetaData.sisyfosLayers) } diff --git a/src/tv2-common/parts/effekt.ts b/src/tv2-common/parts/effekt.ts index b6dc9b313..68a4cef3f 100644 --- a/src/tv2-common/parts/effekt.ts +++ b/src/tv2-common/parts/effekt.ts @@ -16,6 +16,7 @@ import { GetTagForTransition, literal, PartDefinition, + PieceMetaData, TimeFromFrames, TimelineBlueprintExt, TV2BlueprintConfigBase, @@ -117,60 +118,58 @@ export function CreateEffektForPartInner< const fileName = JoinAssetToFolder(config.studio.JingleFolder, file) - pieces.push( - literal({ - externalId, - name: label, - enable: { start: 0, duration: TimeFromFrames(Number(effektConfig.Duration)) }, - outputLayerId: SharedOutputLayers.JINGLE, - sourceLayerId: layers.sourceLayer, - lifespan: PieceLifespan.WithinPart, - pieceType: IBlueprintPieceType.InTransition, - content: literal>({ - fileName, - path: JoinAssetToNetworkPath( - config.studio.JingleNetworkBasePath, - config.studio.JingleFolder, - file, - config.studio.JingleFileExtension - ), // full path on the source network storage - mediaFlowIds: [config.studio.JingleMediaFlowId], - previewFrame: Number(effektConfig.StartAlpha), - ignoreMediaObjectStatus: config.studio.JingleIgnoreStatus, - ignoreBlackFrames: true, - ignoreFreezeFrame: true, - timelineObjects: literal([ - literal({ - id: '', - enable: { - start: 0 - }, - priority: 1, - layer: layers.casparLayer, - content: { - deviceType: TSR.DeviceType.CASPARCG, - type: TSR.TimelineContentTypeCasparCg.MEDIA, - file: fileName - } - }), - ...EnableDSK(config, 'JINGLE', { start: Number(config.studio.CasparPrerollDuration) }), - literal({ - id: '', - enable: { - start: 0 - }, - priority: 1, - layer: layers.sisyfosLayer, - content: { - deviceType: TSR.DeviceType.SISYFOS, - type: TSR.TimelineContentTypeSisyfos.CHANNEL, - isPgm: 1 - } - }) - ]) - }) + pieces.push({ + externalId, + name: label, + enable: { start: 0, duration: TimeFromFrames(Number(effektConfig.Duration)) }, + outputLayerId: SharedOutputLayers.JINGLE, + sourceLayerId: layers.sourceLayer, + lifespan: PieceLifespan.WithinPart, + pieceType: IBlueprintPieceType.InTransition, + content: literal>({ + fileName, + path: JoinAssetToNetworkPath( + config.studio.JingleNetworkBasePath, + config.studio.JingleFolder, + file, + config.studio.JingleFileExtension + ), // full path on the source network storage + mediaFlowIds: [config.studio.JingleMediaFlowId], + previewFrame: Number(effektConfig.StartAlpha), + ignoreMediaObjectStatus: config.studio.JingleIgnoreStatus, + ignoreBlackFrames: true, + ignoreFreezeFrame: true, + timelineObjects: literal([ + literal({ + id: '', + enable: { + start: 0 + }, + priority: 1, + layer: layers.casparLayer, + content: { + deviceType: TSR.DeviceType.CASPARCG, + type: TSR.TimelineContentTypeCasparCg.MEDIA, + file: fileName + } + }), + ...EnableDSK(config, 'JINGLE', { start: Number(config.studio.CasparPrerollDuration) }), + literal({ + id: '', + enable: { + start: 0 + }, + priority: 1, + layer: layers.sisyfosLayer, + content: { + deviceType: TSR.DeviceType.SISYFOS, + type: TSR.TimelineContentTypeSisyfos.CHANNEL, + isPgm: 1 + } + }) + ]) }) - ) + }) return { inTransition: { @@ -190,7 +189,7 @@ export function CreateMixTransitionBlueprintPieceForPart( externalId: string, durationInFrames: number, sourceLayer: string -): IBlueprintPiece { +): IBlueprintPiece { const tags = [ GetTagForTransition( literal({ @@ -209,8 +208,8 @@ function createEffectBlueprintPiece( name: string, sourceLayer: string, tags: string[] -): IBlueprintPiece { - return literal({ +): IBlueprintPiece { + return { enable: { start: 0, duration: Math.max(TimeFromFrames(durationInFrames), 1000) @@ -225,7 +224,7 @@ function createEffectBlueprintPiece( timelineObjects: [], ignoreMediaObjectStatus: true } - }) + } } export function CreateInTransitionForAtemTransitionStyle( @@ -245,7 +244,7 @@ export function CreateDipTransitionBlueprintPieceForPart( externalId: string, durationInFrames: number, sourceLayer: string -): IBlueprintPiece { +): IBlueprintPiece { const tags = [ GetTagForTransition( literal({ diff --git a/src/tv2-common/parts/invalid.ts b/src/tv2-common/parts/invalid.ts index 16b40bb79..b7b1a2cf8 100644 --- a/src/tv2-common/parts/invalid.ts +++ b/src/tv2-common/parts/invalid.ts @@ -1,13 +1,13 @@ import { BlueprintResultPart, IBlueprintPart } from '@tv2media/blueprints-integration' -import { literal, PartDefinition } from 'tv2-common' +import { PartDefinition } from 'tv2-common' export function CreatePartInvalid(ingestPart: PartDefinition, externalIdSuffix?: string): BlueprintResultPart { - const part = literal({ + const part: IBlueprintPart = { externalId: ingestPart.externalId + (externalIdSuffix ? `_${externalIdSuffix}` : ''), title: ingestPart.rawType || 'Unknown', metaData: {}, invalid: true - }) + } return { part, diff --git a/src/tv2-common/parts/kam.ts b/src/tv2-common/parts/kam.ts index 64de85c31..ebd6bdbc1 100644 --- a/src/tv2-common/parts/kam.ts +++ b/src/tv2-common/parts/kam.ts @@ -1,5 +1,5 @@ import { BlueprintResultPart, IBlueprintPart, IShowStyleUserContext } from '@tv2media/blueprints-integration' -import { literal, PartDefinition, PartTime, TV2BlueprintConfigBase, TV2StudioConfigBase } from 'tv2-common' +import { PartDefinition, PartTime, TV2BlueprintConfigBase, TV2StudioConfigBase } from 'tv2-common' export function CreatePartKamBase< StudioConfig extends TV2StudioConfigBase, @@ -12,12 +12,12 @@ export function CreatePartKamBase< ): { part: BlueprintResultPart; duration: number; invalid?: true } { const partTime = PartTime(config, partDefinition, totalWords, false) - const part = literal({ + const part: IBlueprintPart = { externalId: partDefinition.externalId, title: partDefinition.rawType, metaData: {}, expectedDuration: partTime > 0 ? partTime : 0 - }) + } return { part: { diff --git a/src/tv2-common/parts/server.ts b/src/tv2-common/parts/server.ts index 27789dc90..56dd40854 100644 --- a/src/tv2-common/parts/server.ts +++ b/src/tv2-common/parts/server.ts @@ -14,7 +14,7 @@ import { MakeContentServer, MakeContentServerSourceLayers, PieceMetaData, - SisyfosPersistMetaData + ServerPieceMetaData } from 'tv2-common' import { AdlibActionType, PartType, SharedOutputLayers, TallyTags } from 'tv2-constants' import { ActionSelectServerClip } from '../actions' @@ -22,13 +22,9 @@ import { TV2BlueprintConfigBase, TV2StudioConfigBase } from '../blueprintConfig' import { getSourceDuration, GetVTContentProperties } from '../content' import { getServerSeek, ServerPosition, ServerSelectMode } from '../helpers' import { PartDefinition } from '../inewsConversion' -import { literal, SanitizeString } from '../util' +import { SanitizeString } from '../util' import { CreatePartInvalid } from './invalid' -interface PieceMetaDataServer { - userData: ActionSelectServerClip -} - export interface ServerPartProps { voLayer: boolean voLevels: boolean @@ -96,7 +92,7 @@ export async function CreatePartServerBase< const displayTitle = getDisplayTitle(partDefinition) const basePart = getBasePart(partDefinition, displayTitle, actualDuration, file) - const pieces: IBlueprintPiece[] = [] + const pieces: Array> = [] const serverSelectionBlueprintPiece = getServerSelectionBlueprintPiece( partDefinition, @@ -247,29 +243,29 @@ function getServerSelectionBlueprintPiece< context: IShowStyleUserContext, config: ShowStyleConfig, prerollDuration: number -): IBlueprintPiece { +): IBlueprintPiece { const userDataElement = getUserData(partDefinition, contentProps.file, actualDuration, partProps) const contentServerElement = getContentServerElement(partDefinition, partProps, contentProps, layers, context, config) - return literal({ + return { externalId: partDefinition.externalId, name: contentProps.file, enable: { start: 0 }, outputLayerId: SharedOutputLayers.SEC, sourceLayerId: layers.SourceLayer.SelectedServer, lifespan: PieceLifespan.OutOnSegmentEnd, - metaData: literal({ + metaData: { mediaPlayerSessions: [contentProps.mediaPlayerSession], userData: userDataElement, - sisyfosPersistMetaData: literal({ + sisyfosPersistMetaData: { sisyfosLayers: [], acceptPersistAudio: partProps.adLibPix && partProps.voLevels - }) - }), + } + }, content: contentServerElement, tags: [GetTagForServerNext(partDefinition.segmentExternalId, contentProps.file, partProps.voLayer)], prerollDuration - }) + } } function getPgmBlueprintPiece< @@ -282,17 +278,17 @@ function getPgmBlueprintPiece< layers: ServerPartLayers, config: ShowStyleConfig, prerollDuration: number -): IBlueprintPiece { - return literal({ +): IBlueprintPiece { + return { externalId: partDefinition.externalId, name: contentProps.file, enable: { start: 0 }, outputLayerId: SharedOutputLayers.PGM, sourceLayerId: layers.SourceLayer.PgmServer, lifespan: PieceLifespan.WithinPart, - metaData: literal({ + metaData: { mediaPlayerSessions: [contentProps.mediaPlayerSession] - }), + }, content: { ...GetVTContentProperties(config, contentProps), timelineObjects: CutToServer(contentProps.mediaPlayerSession, partDefinition, config, layers.AtemLLayer.MEPgm) @@ -302,5 +298,5 @@ function getPgmBlueprintPiece< TallyTags.SERVER_IS_LIVE ], prerollDuration - }) + } } diff --git a/src/tv2-common/pieces/adlibServer.ts b/src/tv2-common/pieces/adlibServer.ts index 1e704c1d1..0b36bd9f1 100644 --- a/src/tv2-common/pieces/adlibServer.ts +++ b/src/tv2-common/pieces/adlibServer.ts @@ -37,7 +37,7 @@ export async function CreateAdlibServer< const mediaObjectDuration = mediaObjectDurationSec && mediaObjectDurationSec * 1000 const sourceDuration = getSourceDuration(mediaObjectDuration, config.studio.ServerPostrollDuration) - return literal({ + return { externalId: partDefinition.externalId + '-adLib-server', actionId: AdlibActionType.SELECT_SERVER_CLIP, userData: literal({ @@ -70,5 +70,5 @@ export async function CreateAdlibServer< uniquenessId: `${voLayer ? 'vo' : 'server'}_${partDefinition.storyName}_${file}` } // triggerModes: getServerAdLibTriggerModes() /** @todo: uncomment for Server Resume */ - }) + } } diff --git a/src/tv2-common/pieces/script.ts b/src/tv2-common/pieces/script.ts index 63f93a124..66830e66a 100644 --- a/src/tv2-common/pieces/script.ts +++ b/src/tv2-common/pieces/script.ts @@ -4,7 +4,6 @@ import { SharedOutputLayers } from 'tv2-constants' const PREVIEW_CHARACTERS = 30 -// export function AddScript(part: PartDefinition, pieces: IBlueprintPiece[], duration: number, slutord: boolean) { export function AddScript(part: PartDefinition, pieces: IBlueprintPiece[], duration: number, sourceLayerId: string) { if (!pieces.length) { return @@ -16,29 +15,27 @@ export function AddScript(part: PartDefinition, pieces: IBlueprintPiece[], durat } if (script.length) { const stripLength = Math.min(PREVIEW_CHARACTERS, script.length) - pieces.push( - literal({ - externalId: part.externalId, - name: script.slice(0, stripLength), - enable: { - start: 0 - }, - outputLayerId: SharedOutputLayers.MANUS, - sourceLayerId, - lifespan: PieceLifespan.WithinPart, - content: literal>({ - firstWords: script.slice(0, stripLength), - lastWords: script - .replace(/\n/gi, ' ') - .trim() - .slice(script.length - stripLength) - ?.trim(), - fullScript: script, - sourceDuration: duration, - lastModified: part.modified * 1000, - timelineObjects: [] - }) + pieces.push({ + externalId: part.externalId, + name: script.slice(0, stripLength), + enable: { + start: 0 + }, + outputLayerId: SharedOutputLayers.MANUS, + sourceLayerId, + lifespan: PieceLifespan.WithinPart, + content: literal>({ + firstWords: script.slice(0, stripLength), + lastWords: script + .replace(/\n/gi, ' ') + .trim() + .slice(script.length - stripLength) + ?.trim(), + fullScript: script, + sourceDuration: duration, + lastModified: part.modified * 1000, + timelineObjects: [] }) - ) + }) } } diff --git a/src/tv2-common/updatePolicies/shouldRemoveOrphanedPartInstance.ts b/src/tv2-common/updatePolicies/shouldRemoveOrphanedPartInstance.ts index 90e8d449a..626c4a5a1 100644 --- a/src/tv2-common/updatePolicies/shouldRemoveOrphanedPartInstance.ts +++ b/src/tv2-common/updatePolicies/shouldRemoveOrphanedPartInstance.ts @@ -5,5 +5,5 @@ export function shouldRemoveOrphanedPartInstance( _context: IRundownUserContext, partInstance: BlueprintRemoveOrphanedPartInstance ): boolean { - return !(partInstance.partInstance.part.metaData as PartMetaData).dirty + return !(partInstance.partInstance.part.metaData as PartMetaData | undefined)?.dirty } diff --git a/src/tv2-common/updatePolicies/syncIngestUpdateToPartInstance.ts b/src/tv2-common/updatePolicies/syncIngestUpdateToPartInstance.ts index b14d28d4b..c385a68fc 100644 --- a/src/tv2-common/updatePolicies/syncIngestUpdateToPartInstance.ts +++ b/src/tv2-common/updatePolicies/syncIngestUpdateToPartInstance.ts @@ -22,7 +22,6 @@ export function syncIngestUpdateToPartInstanceBase( ...freelyEditableLayers, SharedSourceLayers.PgmGraphicsHeadline, SharedSourceLayers.PgmGraphicsIdent, - SharedSourceLayers.PgmGraphicsIdentPersistent, SharedSourceLayers.PgmGraphicsLower, SharedSourceLayers.PgmGraphicsOverlay, SharedSourceLayers.PgmGraphicsTLF, diff --git a/src/tv2-common/util.ts b/src/tv2-common/util.ts index 0e4f2d0f0..39f213903 100644 --- a/src/tv2-common/util.ts +++ b/src/tv2-common/util.ts @@ -13,7 +13,7 @@ export type WithValuesOfTypes = { [P in keyof T as T[P] extends Q | undefi export type OptionalExceptFor = Partial & Pick export type EmptyBaseObj = OptionalExceptFor, 'layer' | 'enable' | 'classes'> export function createEmptyObject(obj: EmptyBaseObj): TSR.TimelineObjEmpty { - return literal({ + return { id: '', priority: 0, ...obj, @@ -21,7 +21,7 @@ export function createEmptyObject(obj: EmptyBaseObj): TSR.TimelineObjEmpty { deviceType: TSR.DeviceType.ABSTRACT, type: 'empty' } - }) + } } /** diff --git a/src/tv2-constants/enums.ts b/src/tv2-constants/enums.ts index 8eb2b493d..d7f0f6605 100644 --- a/src/tv2-constants/enums.ts +++ b/src/tv2-constants/enums.ts @@ -116,7 +116,6 @@ export function AdlibTagCutToBox(box: number): AdlibTags { } export enum ControlClasses { - ShowIdentGraphic = 'show_ident_graphic', /** Indicates that a DVE is currently on air */ DVEOnAir = 'dve_on_air', ServerOnAir = 'server_on_air', @@ -148,8 +147,7 @@ export enum AdlibActionType { TAKE_WITH_TRANSITION = 'take_with_transition', RECALL_LAST_LIVE = 'recall_last_live', RECALL_LAST_DVE = 'recall_last_dve', - FADE_DOWN_PERSISTED_AUDIO_LEVELS = 'fade_down_persisted_audio_levels', - PLAY_GRAPHICS = 'play_graphics' + FADE_DOWN_PERSISTED_AUDIO_LEVELS = 'fade_down_persisted_audio_levels' } export enum TallyTags { @@ -237,7 +235,6 @@ export enum SharedSourceLayers { // Graphics PgmGraphicsIdent = 'studio0_graphicsIdent', - PgmGraphicsIdentPersistent = 'studio0_graphicsIdent_persistent', PgmGraphicsTop = 'studio0_graphicsTop', PgmGraphicsLower = 'studio0_graphicsLower', PgmGraphicsHeadline = 'studio0_graphicsHeadline', diff --git a/src/tv2_afvd_showstyle/__tests__/actions.spec.ts b/src/tv2_afvd_showstyle/__tests__/actions.spec.ts index 87cd90246..b84748084 100644 --- a/src/tv2_afvd_showstyle/__tests__/actions.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/actions.spec.ts @@ -406,7 +406,7 @@ async function getTransitionPiece( } function getATEMMEObj(piece: IBlueprintPieceInstance): TSR.TimelineObjAtemME { - const atemObj = (piece.piece.content!.timelineObjects as TSR.TSRTimelineObj[]).find( + const atemObj = (piece.piece.content.timelineObjects as TSR.TSRTimelineObj[]).find( obj => obj.layer === AtemLLayer.AtemMEProgram && obj.content.deviceType === TSR.DeviceType.ATEM && @@ -792,9 +792,9 @@ describe('Camera shortcuts on server', () => { const context = makeMockContext('cut', 'cam', 'cam') context.currentPieceInstances = [ - literal({ + { _id: 'serverPieceInstance', - piece: literal({ + piece: { _id: 'Server Current', enable: { start: 0 @@ -807,9 +807,9 @@ describe('Camera shortcuts on server', () => { content: { timelineObjects: [] } - }), + }, partInstanceId: '' - }) + } ] context.nextPart = undefined @@ -835,9 +835,9 @@ describe('Camera shortcuts on server', () => { const context = makeMockContext('cut', 'cam', 'cam') context.currentPieceInstances = [ - literal({ + { _id: 'serverPieceInstance', - piece: literal({ + piece: { _id: 'Server Current', enable: { start: 0 @@ -850,9 +850,9 @@ describe('Camera shortcuts on server', () => { content: { timelineObjects: [] } - }), + }, partInstanceId: '' - }) + } ] context.nextPart = undefined @@ -880,9 +880,9 @@ describe('Camera shortcuts on VO', () => { const context = makeMockContext('cut', 'cam', 'cam') context.currentPieceInstances = [ - literal({ + { _id: 'voPieceInstance', - piece: literal({ + piece: { _id: 'VO Current', enable: { start: 0 @@ -895,9 +895,9 @@ describe('Camera shortcuts on VO', () => { content: { timelineObjects: [] } - }), + }, partInstanceId: '' - }) + } ] context.nextPart = undefined @@ -923,9 +923,9 @@ describe('Camera shortcuts on VO', () => { const context = makeMockContext('cut', 'cam', 'cam') context.currentPieceInstances = [ - literal({ + { _id: 'voPieceInstance', - piece: literal({ + piece: { _id: 'VO Current', enable: { start: 0 @@ -938,9 +938,9 @@ describe('Camera shortcuts on VO', () => { content: { timelineObjects: [] } - }), + }, partInstanceId: '' - }) + } ] context.nextPart = undefined diff --git a/src/tv2_afvd_showstyle/__tests__/blueprint.spec.ts b/src/tv2_afvd_showstyle/__tests__/blueprint.spec.ts index fff09412d..acce40bf4 100644 --- a/src/tv2_afvd_showstyle/__tests__/blueprint.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/blueprint.spec.ts @@ -1,6 +1,5 @@ import { BlueprintResultSegment, - IBlueprintActionManifest, IBlueprintActionManifestDisplayContent, IngestSegment } from '@tv2media/blueprints-integration' @@ -172,7 +171,7 @@ describe('AFVD Blueprint', () => { ]) expect(fullPart.adLibPieces).toHaveLength(0) expect(fullPart.actions).toHaveLength(1) - const fullAdlibAction = fullPart.actions![0] as IBlueprintActionManifest + const fullAdlibAction = fullPart.actions[0] expect(fullAdlibAction).toBeTruthy() expect((fullAdlibAction.display as IBlueprintActionManifestDisplayContent).sourceLayerId).toBe( SharedSourceLayers.PgmPilot @@ -253,7 +252,7 @@ describe('AFVD Blueprint', () => { expect(fullPart.pieces).toHaveLength(2) expect(fullPart.adLibPieces).toHaveLength(0) expect(fullPart.actions).toHaveLength(1) - const fullAdlibAction = fullPart.actions![0] as IBlueprintActionManifest + const fullAdlibAction = fullPart.actions[0] expect(fullAdlibAction).toBeTruthy() expect((fullAdlibAction.display as IBlueprintActionManifestDisplayContent).sourceLayerId).toBe( SharedSourceLayers.PgmPilot @@ -305,7 +304,7 @@ describe('AFVD Blueprint', () => { expect(fullPart.pieces).toHaveLength(3) expect(fullPart.adLibPieces).toHaveLength(0) expect(fullPart.actions).toHaveLength(1) - const fullAdlibAction = fullPart.actions![0] as IBlueprintActionManifest + const fullAdlibAction = fullPart.actions[0] expect(fullAdlibAction).toBeTruthy() expect((fullAdlibAction.display as IBlueprintActionManifestDisplayContent).sourceLayerId).toBe( SharedSourceLayers.PgmPilot @@ -356,7 +355,7 @@ describe('AFVD Blueprint', () => { expect(fullPart.adLibPieces).toHaveLength(0) expect(fullPart.actions).toHaveLength(1) expect(fullPart.actions).toHaveLength(1) - const fullAdlibAction = fullPart.actions![0] as IBlueprintActionManifest + const fullAdlibAction = fullPart.actions[0] expect(fullAdlibAction).toBeTruthy() expect((fullAdlibAction.display as IBlueprintActionManifestDisplayContent).sourceLayerId).toBe( SharedSourceLayers.PgmPilot @@ -576,7 +575,7 @@ describe('AFVD Blueprint', () => { expect(fullPart.pieces).toHaveLength(2) expect(fullPart.adLibPieces).toHaveLength(0) expect(fullPart.actions).toHaveLength(1) - const fullAdlibAction = fullPart.actions![0] as IBlueprintActionManifest + const fullAdlibAction = fullPart.actions[0] expect(fullAdlibAction).toBeTruthy() expect((fullAdlibAction.display as IBlueprintActionManifestDisplayContent).sourceLayerId).toBe( SharedSourceLayers.PgmPilot diff --git a/src/tv2_afvd_showstyle/__tests__/layers-check.ts b/src/tv2_afvd_showstyle/__tests__/layers-check.ts index fa0966dae..7b99f7217 100644 --- a/src/tv2_afvd_showstyle/__tests__/layers-check.ts +++ b/src/tv2_afvd_showstyle/__tests__/layers-check.ts @@ -8,7 +8,7 @@ import { TSR } from '@tv2media/blueprints-integration' -import { GetDSKSourceLayerNames, literal } from 'tv2-common' +import { GetDSKSourceLayerNames } from 'tv2-common' import mappingsDefaults, { getMediaPlayerMappings } from '../../tv2_afvd_studio/migrations/mappings-defaults' import { ATEMModel } from '../../types/atem' import { getConfig } from '../helpers/config' @@ -33,10 +33,10 @@ export function checkAllLayers( .sort() const allOutputLayers = _.map(OutputlayerDefaults, m => m._id) - const allMappings = literal({ + const allMappings: BlueprintMappings = { ...mappingsDefaults, ...getMediaPlayerMappings(config.mediaPlayers) - }) + } const validateObject = (obj: TimelineObjectCoreExt) => { const isAbstract = obj.content.deviceType === TSR.DeviceType.ABSTRACT diff --git a/src/tv2_afvd_showstyle/getRundown.ts b/src/tv2_afvd_showstyle/getRundown.ts index 3878b9961..f3c884548 100644 --- a/src/tv2_afvd_showstyle/getRundown.ts +++ b/src/tv2_afvd_showstyle/getRundown.ts @@ -4,7 +4,6 @@ import { GraphicsContent, IBlueprintActionManifest, IBlueprintAdLibPiece, - IBlueprintRundown, IBlueprintShowStyleVariant, IngestRundown, IShowStyleUserContext, @@ -36,7 +35,6 @@ import { literal, PieceMetaData, replaySourceName, - SisyfosPersistMetaData, SourceDefinitionKam, SourceInfo, SourceInfoToSourceDefinition, @@ -81,13 +79,13 @@ export function getRundown(context: IShowStyleUserContext, ingestRundown: Ingest const config = getShowStyleConfig(context) return { - rundown: literal({ + rundown: { externalId: ingestRundown.externalId, name: ingestRundown.name, timing: { type: PlaylistTimingType.None } - }), + }, globalAdLibPieces: getGlobalAdLibPiecesAFVD(context, config), globalActions: getGlobalAdlibActionsAFVD(context, config), baseline: getBaseline(config) @@ -95,8 +93,8 @@ export function getRundown(context: IShowStyleUserContext, ingestRundown: Ingest } function getGlobalAdLibPiecesAFVD(context: IStudioUserContext, config: BlueprintConfig): IBlueprintAdLibPiece[] { - function makeEVSAdLibs(info: SourceInfo, rank: number, vo: boolean): IBlueprintAdLibPiece[] { - const res: IBlueprintAdLibPiece[] = [] + function makeEVSAdLibs(info: SourceInfo, rank: number, vo: boolean): Array> { + const res: Array> = [] res.push({ externalId: 'delayed', name: replaySourceName(info.id, vo), @@ -106,12 +104,12 @@ function getGlobalAdLibPiecesAFVD(context: IStudioUserContext, config: Blueprint expectedDuration: 0, lifespan: PieceLifespan.WithinPart, toBeQueued: true, - metaData: literal({ + metaData: { sisyfosPersistMetaData: { sisyfosLayers: info.sisyfosLayers ?? [], acceptPersistAudio: vo } - }), + }, tags: [AdlibTags.ADLIB_QUEUE_NEXT, vo ? AdlibTags.ADLIB_VO_AUDIO_LEVEL : AdlibTags.ADLIB_FULL_AUDIO_LEVEL], content: { ignoreMediaObjectStatus: true, @@ -135,12 +133,11 @@ function getGlobalAdLibPiecesAFVD(context: IStudioUserContext, config: Blueprint ] } }) - return res } - function makeRemoteAdLibs(info: SourceInfo, rank: number): IBlueprintAdLibPiece[] { - const res: IBlueprintAdLibPiece[] = [] + function makeRemoteAdLibs(info: SourceInfo, rank: number): Array> { + const res: Array> = [] const eksternSisyfos = GetSisyfosTimelineObjForRemote(config, info) res.push({ externalId: 'live', @@ -152,11 +149,11 @@ function getGlobalAdLibPiecesAFVD(context: IStudioUserContext, config: Blueprint lifespan: PieceLifespan.WithinPart, toBeQueued: true, metaData: { - sisyfosPersistMetaData: literal({ + sisyfosPersistMetaData: { sisyfosLayers: info.sisyfosLayers ?? [], wantsToPersistAudio: info.wantsToPersistAudio, acceptPersistAudio: info.acceptPersistAudio - }) + } }, tags: [AdlibTags.ADLIB_QUEUE_NEXT], content: { @@ -185,8 +182,8 @@ function getGlobalAdLibPiecesAFVD(context: IStudioUserContext, config: Blueprint } // aux adlibs - function makeRemoteAuxStudioAdLibs(info: SourceInfo, rank: number): IBlueprintAdLibPiece[] { - const res: IBlueprintAdLibPiece[] = [] + function makeRemoteAuxStudioAdLibs(info: SourceInfo, rank: number): Array> { + const res: Array> = [] res.push({ externalId: 'auxstudio', name: info.id + '', @@ -196,11 +193,11 @@ function getGlobalAdLibPiecesAFVD(context: IStudioUserContext, config: Blueprint expectedDuration: 0, lifespan: PieceLifespan.OutOnShowStyleEnd, metaData: { - sisyfosPersistMetaData: literal({ + sisyfosPersistMetaData: { sisyfosLayers: info.sisyfosLayers ?? [], wantsToPersistAudio: info.wantsToPersistAudio, acceptPersistAudio: info.acceptPersistAudio - }) + } }, tags: [AdlibTags.ADLIB_TO_STUDIO_SCREEN_AUX], content: { @@ -545,35 +542,33 @@ function getGlobalAdlibActionsAFVD(_context: IStudioUserContext, config: Bluepri const name = `${info.type} ${info.id}` const layer = info.type === SourceInfoType.KAM ? SourceLayer.PgmCam : SourceLayer.PgmLive - const userData = literal({ + const userData: ActionCutSourceToBox = { type: AdlibActionType.CUT_SOURCE_TO_BOX, name, box, sourceDefinition: SourceInfoToSourceDefinition(info) + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.CUT_SOURCE_TO_BOX, + userData, + userDataManifest: {}, + display: { + _rank: rank + 0.1 * box, + label: t(`${name} inp ${box + 1}`), + sourceLayerId: layer, + outputLayerId: SharedOutputLayers.SEC, + content: {}, + tags: [AdlibTagCutToBox(box)] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.CUT_SOURCE_TO_BOX, - userData, - userDataManifest: {}, - display: { - _rank: rank + 0.1 * box, - label: t(`${name} inp ${box + 1}`), - sourceLayerId: layer, - outputLayerId: SharedOutputLayers.SEC, - content: {}, - tags: [AdlibTagCutToBox(box)] - } - }) - ) } } function makeAdlibBoxesActionsReplay(info: SourceInfo, rank: number, vo: boolean) { for (let box = 0; box < NUMBER_OF_DVE_BOXES; box++) { const name = replaySourceName(info.id, vo) - const userData = literal({ + const userData: ActionCutSourceToBox = { type: AdlibActionType.CUT_SOURCE_TO_BOX, name, box, @@ -584,76 +579,70 @@ function getGlobalAdlibActionsAFVD(_context: IStudioUserContext, config: Bluepri raw: '', name } + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.CUT_SOURCE_TO_BOX, + userData, + userDataManifest: {}, + display: { + _rank: rank + 0.1 * box, + label: t(`${name} inp ${box + 1}`), + sourceLayerId: SourceLayer.PgmLocal, + outputLayerId: SharedOutputLayers.SEC, + content: {}, + tags: [AdlibTagCutToBox(box), vo ? AdlibTags.ADLIB_VO_AUDIO_LEVEL : AdlibTags.ADLIB_FULL_AUDIO_LEVEL] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.CUT_SOURCE_TO_BOX, - userData, - userDataManifest: {}, - display: { - _rank: rank + 0.1 * box, - label: t(`${name} inp ${box + 1}`), - sourceLayerId: SourceLayer.PgmLocal, - outputLayerId: SharedOutputLayers.SEC, - content: {}, - tags: [AdlibTagCutToBox(box), vo ? AdlibTags.ADLIB_VO_AUDIO_LEVEL : AdlibTags.ADLIB_FULL_AUDIO_LEVEL] - } - }) - ) } } function makeServerAdlibBoxesActions(rank: number) { for (let box = 0; box < NUMBER_OF_DVE_BOXES; box++) { - const userData = literal({ + const userData: ActionCutSourceToBox = { type: AdlibActionType.CUT_SOURCE_TO_BOX, name: `SERVER`, box, sourceDefinition: { sourceType: SourceType.SERVER } + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.CUT_SOURCE_TO_BOX, + userData, + userDataManifest: {}, + display: { + _rank: rank + 0.1 * box, + label: t(`Server inp ${box + 1}`), + sourceLayerId: SourceLayer.PgmServer, + outputLayerId: SharedOutputLayers.SEC, + content: {}, + tags: [AdlibTagCutToBox(box)] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.CUT_SOURCE_TO_BOX, - userData, - userDataManifest: {}, - display: { - _rank: rank + 0.1 * box, - label: t(`Server inp ${box + 1}`), - sourceLayerId: SourceLayer.PgmServer, - outputLayerId: SharedOutputLayers.SEC, - content: {}, - tags: [AdlibTagCutToBox(box)] - } - }) - ) } } function makeCutCameraActions(info: SourceInfo, queue: boolean, rank: number) { const sourceDefinition = SourceInfoToSourceDefinition(info) as SourceDefinitionKam - const userData = literal({ + const userData: ActionCutToCamera = { type: AdlibActionType.CUT_TO_CAMERA, queue, sourceDefinition + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.CUT_TO_CAMERA, + userData, + userDataManifest: {}, + display: { + _rank: rank, + label: t(sourceDefinition.name), + sourceLayerId: SourceLayer.PgmCam, + outputLayerId: SharedOutputLayers.PGM, + content: {}, + tags: queue ? [AdlibTags.ADLIB_QUEUE_NEXT] : [AdlibTags.ADLIB_CUT_DIRECT] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.CUT_TO_CAMERA, - userData, - userDataManifest: {}, - display: { - _rank: rank, - label: t(sourceDefinition.name), - sourceLayerId: SourceLayer.PgmCam, - outputLayerId: SharedOutputLayers.PGM, - content: {}, - tags: queue ? [AdlibTags.ADLIB_QUEUE_NEXT] : [AdlibTags.ADLIB_CUT_DIRECT] - } - }) - ) } config.sources.cameras @@ -675,24 +664,22 @@ function getGlobalAdlibActionsAFVD(_context: IStudioUserContext, config: Bluepri }) function makeRecallLastLiveAction() { - const userData = literal({ + const userData: ActionRecallLastLive = { type: AdlibActionType.RECALL_LAST_LIVE + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.RECALL_LAST_LIVE, + userData, + userDataManifest: {}, + display: { + _rank: 1, + label: t('Last Live'), + sourceLayerId: SourceLayer.PgmLive, + outputLayerId: SharedOutputLayers.PGM, + tags: [AdlibTags.ADLIB_RECALL_LAST_LIVE] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.RECALL_LAST_LIVE, - userData, - userDataManifest: {}, - display: { - _rank: 1, - label: t('Last Live'), - sourceLayerId: SourceLayer.PgmLive, - outputLayerId: SharedOutputLayers.PGM, - tags: [AdlibTags.ADLIB_RECALL_LAST_LIVE] - } - }) - ) } makeRecallLastLiveAction() @@ -718,13 +705,13 @@ function getGlobalAdlibActionsAFVD(_context: IStudioUserContext, config: Bluepri makeServerAdlibBoxesActions(globalRank++) - function makeClearGraphicsAction() { - const userData = literal({ + function makeClearGraphicsAction(): IBlueprintActionManifest { + const userData: ActionClearGraphics = { type: AdlibActionType.CLEAR_GRAPHICS, sendCommands: true, label: 'GFX Clear' - }) - return literal({ + } + return { externalId: generateExternalId(_context, userData), actionId: AdlibActionType.CLEAR_GRAPHICS, userData, @@ -739,16 +726,16 @@ function getGlobalAdlibActionsAFVD(_context: IStudioUserContext, config: Bluepri currentPieceTags: [TallyTags.GFX_CLEAR], nextPieceTags: [TallyTags.GFX_CLEAR] } - }) + } } - function makeClearGraphicsAltudAction() { - const userData = literal({ + function makeClearGraphicsAltudAction(): IBlueprintActionManifest { + const userData: ActionClearGraphics = { type: AdlibActionType.CLEAR_GRAPHICS, sendCommands: false, label: 'GFX Altud' - }) - return literal({ + } + return { externalId: generateExternalId(_context, userData), actionId: AdlibActionType.CLEAR_GRAPHICS, userData, @@ -763,73 +750,66 @@ function getGlobalAdlibActionsAFVD(_context: IStudioUserContext, config: Bluepri currentPieceTags: [TallyTags.GFX_ALTUD], nextPieceTags: [TallyTags.GFX_ALTUD] } - }) + } } blueprintActions.push(makeClearGraphicsAction(), makeClearGraphicsAltudAction()) blueprintActions.push(...GetTransitionAdLibActions(config, 800)) - const recallLastLiveDveUserData = literal({ + const recallLastLiveDveUserData: ActionRecallLastDVE = { type: AdlibActionType.RECALL_LAST_DVE + } + blueprintActions.push({ + externalId: generateExternalId(_context, recallLastLiveDveUserData), + actionId: AdlibActionType.RECALL_LAST_DVE, + userData: recallLastLiveDveUserData, + userDataManifest: {}, + display: { + _rank: 1, + label: t('Last DVE'), + sourceLayerId: SourceLayer.PgmDVEAdLib, + outputLayerId: 'pgm', + tags: [AdlibTags.ADLIB_RECALL_LAST_DVE] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, recallLastLiveDveUserData), - actionId: AdlibActionType.RECALL_LAST_DVE, - userData: recallLastLiveDveUserData, - userDataManifest: {}, - display: { - _rank: 1, - label: t('Last DVE'), - sourceLayerId: SourceLayer.PgmDVEAdLib, - outputLayerId: 'pgm', - tags: [AdlibTags.ADLIB_RECALL_LAST_DVE] - } - }) - ) _.each(config.showStyle.DVEStyles, (dveConfig, i) => { - // const boxSources = ['', '', '', ''] - const userData = literal({ + const userData: ActionSelectDVELayout = { type: AdlibActionType.SELECT_DVE_LAYOUT, config: dveConfig + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.SELECT_DVE_LAYOUT, + userData, + userDataManifest: {}, + display: { + _rank: 200 + i, + label: t(dveConfig.DVEName), + sourceLayerId: SourceLayer.PgmDVEAdLib, + outputLayerId: SharedOutputLayers.PGM, + tags: [AdlibTags.ADLIB_SELECT_DVE_LAYOUT, dveConfig.DVEName] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.SELECT_DVE_LAYOUT, - userData, - userDataManifest: {}, - display: { - _rank: 200 + i, - label: t(dveConfig.DVEName), - sourceLayerId: SourceLayer.PgmDVEAdLib, - outputLayerId: SharedOutputLayers.PGM, - tags: [AdlibTags.ADLIB_SELECT_DVE_LAYOUT, dveConfig.DVEName] - } - }) - ) }) - const fadeDownPersistedAudioLevelsUserData = literal({ + const fadeDownPersistedAudioLevelsUserData: ActionFadeDownPersistedAudioLevels = { type: AdlibActionType.FADE_DOWN_PERSISTED_AUDIO_LEVELS + } + blueprintActions.push({ + externalId: generateExternalId(_context, fadeDownPersistedAudioLevelsUserData), + actionId: AdlibActionType.FADE_DOWN_PERSISTED_AUDIO_LEVELS, + userData: fadeDownPersistedAudioLevelsUserData, + userDataManifest: {}, + display: { + _rank: 300, + label: t('Fade down persisted audio levels'), + sourceLayerId: SourceLayer.PgmSisyfosAdlibs, + outputLayerId: SharedOutputLayers.SEC, + tags: [AdlibTags.ADLIB_FADE_DOWN_PERSISTED_AUDIO_LEVELS] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, fadeDownPersistedAudioLevelsUserData), - actionId: AdlibActionType.FADE_DOWN_PERSISTED_AUDIO_LEVELS, - userData: fadeDownPersistedAudioLevelsUserData, - userDataManifest: {}, - display: { - _rank: 300, - label: t('Fade down persisted audio levels'), - sourceLayerId: SourceLayer.PgmSisyfosAdlibs, - outputLayerId: SharedOutputLayers.SEC, - tags: [AdlibTags.ADLIB_FADE_DOWN_PERSISTED_AUDIO_LEVELS] - } - }) - ) return blueprintActions } diff --git a/src/tv2_afvd_showstyle/getSegment.ts b/src/tv2_afvd_showstyle/getSegment.ts index 043572f0e..bb910eedc 100644 --- a/src/tv2_afvd_showstyle/getSegment.ts +++ b/src/tv2_afvd_showstyle/getSegment.ts @@ -62,8 +62,8 @@ export async function getSegment( } } -export function CreatePartContinuity(config: ShowStyleConfig, ingestSegment: IngestSegment) { - return literal({ +export function CreatePartContinuity(config: ShowStyleConfig, ingestSegment: IngestSegment): BlueprintResultPart { + return { part: { externalId: `${ingestSegment.externalId}-CONTINUITY`, title: 'CONTINUITY', @@ -105,7 +105,7 @@ export function CreatePartContinuity(config: ShowStyleConfig, ingestSegment: Ing ], adLibPieces: [], actions: [] - }) + } } function insertSpecialPieces( diff --git a/src/tv2_afvd_showstyle/helpers/pieces/__tests__/grafikViz.spec.ts b/src/tv2_afvd_showstyle/helpers/pieces/__tests__/grafikViz.spec.ts index 09d149f28..81fa9afbd 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/__tests__/grafikViz.spec.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/__tests__/grafikViz.spec.ts @@ -11,20 +11,13 @@ import { AtemLLayerDSK, CueDefinitionGraphic, GraphicInternal, + GraphicPieceMetaData, GraphicPilot, literal, PartDefinitionKam, PieceMetaData } from 'tv2-common' -import { - AbstractLLayer, - AdlibTags, - CueType, - PartType, - SharedGraphicLLayer, - SharedOutputLayers, - SourceType -} from 'tv2-constants' +import { AdlibTags, CueType, PartType, SharedGraphicLLayer, SharedOutputLayers, SourceType } from 'tv2-constants' import { SegmentUserContext } from '../../../../__mocks__/context' import { parseConfig as parseStudioConfig } from '../../../../tv2_afvd_studio/helpers/config' import mappingsDefaults from '../../../../tv2_afvd_studio/migrations/mappings-defaults' @@ -116,7 +109,7 @@ describe('grafik piece', () => { cue.adlib ? { rank: 0 } : undefined ) expect(pieces).toEqual([ - literal({ + literal>({ externalId: partId, name: 'bund - Odense\n - Copenhagen', enable: { @@ -124,11 +117,12 @@ describe('grafik piece', () => { duration: 4000 }, lifespan: PieceLifespan.WithinPart, - metaData: literal({ + metaData: { sisyfosPersistMetaData: { sisyfosLayers: [] - } - }), + }, + belongsToRemotePart: false + }, outputLayerId: SharedOutputLayers.OVERLAY, sourceLayerId: SourceLayer.PgmGraphicsLower, content: literal>({ @@ -419,7 +413,7 @@ describe('grafik piece', () => { cue.adlib ? { rank: 0 } : undefined ) expect(pieces).toEqual([ - literal({ + literal>({ externalId: partId, name: 'bund - Odense\n - Copenhagen', enable: { @@ -427,11 +421,12 @@ describe('grafik piece', () => { duration: 4000 }, lifespan: PieceLifespan.WithinPart, - metaData: literal({ + metaData: { sisyfosPersistMetaData: { sisyfosLayers: [] - } - }), + }, + belongsToRemotePart: false + }, outputLayerId: SharedOutputLayers.OVERLAY, sourceLayerId: SourceLayer.PgmGraphicsLower, content: literal>({ @@ -497,18 +492,19 @@ describe('grafik piece', () => { cue.adlib ? { rank: 0 } : undefined ) expect(pieces).toEqual([ - literal({ + literal>({ externalId: partId, name: 'bund - Odense\n - Copenhagen', enable: { start: 10000 }, lifespan: PieceLifespan.WithinPart, - metaData: literal({ + metaData: { sisyfosPersistMetaData: { sisyfosLayers: [] - } - }), + }, + belongsToRemotePart: false + }, outputLayerId: SharedOutputLayers.OVERLAY, sourceLayerId: SourceLayer.PgmGraphicsLower, content: literal>({ @@ -571,20 +567,21 @@ describe('grafik piece', () => { cue.adlib ? { rank: 0 } : undefined ) expect(pieces).toEqual([ - literal({ + literal>({ externalId: partId, name: 'direkte - KØBENHAVN', enable: { start: 0 }, - lifespan: PieceLifespan.OutOnSegmentEnd, - metaData: literal({ + lifespan: PieceLifespan.WithinPart, + metaData: { sisyfosPersistMetaData: { sisyfosLayers: [] - } - }), + }, + belongsToRemotePart: false + }, outputLayerId: SharedOutputLayers.OVERLAY, - sourceLayerId: SourceLayer.PgmGraphicsIdentPersistent, + sourceLayerId: SourceLayer.PgmGraphicsIdent, content: literal>({ fileName: 'direkte', path: 'direkte', @@ -609,35 +606,6 @@ describe('grafik piece', () => { dskEnableObj ]) }) - }), - literal({ - externalId: partId, - name: 'direkte - KØBENHAVN', - enable: { - start: 0 - }, - lifespan: PieceLifespan.WithinPart, - metaData: literal({ - sisyfosPersistMetaData: { - sisyfosLayers: [] - } - }), - outputLayerId: SharedOutputLayers.OVERLAY, - sourceLayerId: SourceLayer.PgmGraphicsIdent, - content: { - timelineObjects: [ - literal({ - id: '', - enable: { - while: '1' - }, - layer: AbstractLLayer.IdentMarker, - content: { - deviceType: TSR.DeviceType.ABSTRACT - } - }) - ] - } }) ]) }) @@ -674,7 +642,7 @@ describe('grafik piece', () => { cue.adlib ? { rank: 0 } : undefined ) expect(pieces).toEqual([ - literal({ + literal>({ externalId: partId, name: 'arkiv - unnamed org', enable: { @@ -682,11 +650,12 @@ describe('grafik piece', () => { duration: 4000 }, lifespan: PieceLifespan.WithinPart, - metaData: literal({ + metaData: { sisyfosPersistMetaData: { sisyfosLayers: [] - } - }), + }, + belongsToRemotePart: false + }, outputLayerId: SharedOutputLayers.OVERLAY, sourceLayerId: SourceLayer.PgmGraphicsIdent, content: literal>({ @@ -799,7 +768,6 @@ describe('grafik piece', () => { }), outputLayerId: SharedOutputLayers.OVERLAY, sourceLayerId: SourceLayer.PgmGraphicsTop, - expectedDuration: 4000, tags: ['flow_producer'], uniquenessId: 'gfx_tlftoptlive - Line 1\n - Line 2_studio0_graphicsTop_overlay_flow', content: literal>({ diff --git a/src/tv2_afvd_showstyle/helpers/pieces/__tests__/lyd.spec.ts b/src/tv2_afvd_showstyle/helpers/pieces/__tests__/lyd.spec.ts index a6bcd1e8b..53fdaea3a 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/__tests__/lyd.spec.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/__tests__/lyd.spec.ts @@ -140,36 +140,6 @@ describe('lyd', () => { expect(context.getNotes()[0].type).toEqual(NoteType.NOTIFY_USER_WARNING) }) - test('Lyd not configured', () => { - const parsedCue = ParseCue(['LYD=SN_MISSING', ';0.00-0.10'], CONFIG) as CueDefinitionLYD - const pieces: IBlueprintPiece[] = [] - const adlibPieces: IBlueprintAdLibPiece[] = [] - const actions: IBlueprintActionManifest[] = [] - - const context = makeMockContext() - - EvaluateLYD( - context, - { - showStyle: (defaultShowStyleConfig as unknown) as ShowStyleConfig, - studio: (defaultStudioConfig as unknown) as StudioConfig, - sources: EMPTY_SOURCE_CONFIG, - mediaPlayers: [], - dsk: defaultDSKConfig, - selectedGraphicsSetup: DEFAULT_GRAPHICS_SETUP - }, - pieces, - adlibPieces, - actions, - parsedCue, - MOCK_PART - ) - - expect(pieces.length).toEqual(0) - expect(context.getNotes().length).toEqual(1) - expect(context.getNotes()[0].type).toEqual(NoteType.NOTIFY_USER_WARNING) - }) - test('Lyd adlib', () => { const parsedCue = ParseCue(['LYD=SN_INTRO', ';x.xx'], CONFIG) as CueDefinitionLYD const pieces: IBlueprintPiece[] = [] diff --git a/src/tv2_afvd_showstyle/helpers/pieces/__tests__/telefon.spec.ts b/src/tv2_afvd_showstyle/helpers/pieces/__tests__/telefon.spec.ts index f4b8745f0..fb075a18d 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/__tests__/telefon.spec.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/__tests__/telefon.spec.ts @@ -12,9 +12,9 @@ import { CueDefinitionGraphic, CueDefinitionTelefon, GraphicInternal, + GraphicPieceMetaData, literal, - PartDefinitionKam, - PieceMetaData + PartDefinitionKam } from 'tv2-common' import { CueType, PartType, SharedGraphicLLayer, SharedOutputLayers, SourceType } from 'tv2-constants' import { SegmentUserContext } from '../../../../__mocks__/context' @@ -106,7 +106,7 @@ describe('telefon', () => { cue ) expect(pieces).toEqual([ - literal({ + literal>({ externalId: partId, name: 'TLF 1', enable: { @@ -115,11 +115,12 @@ describe('telefon', () => { outputLayerId: SharedOutputLayers.OVERLAY, sourceLayerId: SourceLayer.PgmGraphicsLower, lifespan: PieceLifespan.WithinPart, - metaData: literal({ + metaData: { + belongsToRemotePart: false, sisyfosPersistMetaData: { sisyfosLayers: [] } - }), + }, content: literal>({ fileName: 'bund', path: 'bund', diff --git a/src/tv2_afvd_showstyle/helpers/pieces/adlib.ts b/src/tv2_afvd_showstyle/helpers/pieces/adlib.ts index 49655d543..3c2864882 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/adlib.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/adlib.ts @@ -27,7 +27,7 @@ import { MakeContentDVE } from '../content/dve' export async function EvaluateAdLib( context: IShowStyleUserContext, config: BlueprintConfig, - adLibPieces: IBlueprintAdLibPiece[], + adLibPieces: Array>, actions: IBlueprintActionManifest[], mediaSubscriptions: HackPartMediaObjectSubscription[], partId: string, @@ -100,33 +100,31 @@ export async function EvaluateAdLib( const content = MakeContentDVE(context, config, partDefinition, cueDVE, rawTemplate, false, true) - adLibPieces.push( - literal({ - _rank: rank, - externalId: partId, - name: `DVE: ${parsedCue.variant}`, - sourceLayerId: SourceLayer.PgmDVE, - outputLayerId: SharedOutputLayers.PGM, - uniquenessId: getUniquenessIdDVE(cueDVE), - toBeQueued: true, - content: content.content, - invalid: !content.valid, - lifespan: PieceLifespan.WithinPart, - metaData: literal({ - sources: cueDVE.sources, - config: rawTemplate, - userData: literal({ - type: AdlibActionType.SELECT_DVE, - config: cueDVE, - videoId: partDefinition.fields.videoId, - segmentExternalId: partDefinition.segmentExternalId - }), - sisyfosPersistMetaData: { - sisyfosLayers: [] - } + adLibPieces.push({ + _rank: rank, + externalId: partId, + name: `DVE: ${parsedCue.variant}`, + sourceLayerId: SourceLayer.PgmDVE, + outputLayerId: SharedOutputLayers.PGM, + uniquenessId: getUniquenessIdDVE(cueDVE), + toBeQueued: true, + content: content.content, + invalid: !content.valid, + lifespan: PieceLifespan.WithinPart, + metaData: literal({ + sources: cueDVE.sources, + config: rawTemplate, + userData: literal({ + type: AdlibActionType.SELECT_DVE, + config: cueDVE, + videoId: partDefinition.fields.videoId, + segmentExternalId: partDefinition.segmentExternalId }), - tags: [AdlibTags.ADLIB_FLOW_PRODUCER] - }) - ) + sisyfosPersistMetaData: { + sisyfosLayers: [] + } + }), + tags: [AdlibTags.ADLIB_FLOW_PRODUCER] + }) } } diff --git a/src/tv2_afvd_showstyle/helpers/pieces/clearGrafiks.ts b/src/tv2_afvd_showstyle/helpers/pieces/clearGrafiks.ts index 11919187c..202258d60 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/clearGrafiks.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/clearGrafiks.ts @@ -25,7 +25,6 @@ export function EvaluateClearGrafiks( ;[ SourceLayer.PgmGraphicsIdent, - SourceLayer.PgmGraphicsIdentPersistent, SourceLayer.PgmGraphicsTop, SourceLayer.PgmGraphicsLower, SourceLayer.PgmGraphicsHeadline, @@ -49,34 +48,32 @@ export function EvaluateClearGrafiks( }) }) - pieces.push( - literal({ - externalId: partId, - name: 'CLEAR', - ...CreateTimingEnable(parsedCue, GetDefaultOut(config)), - outputLayerId: SharedOutputLayers.SEC, - sourceLayerId: SourceLayer.PgmAdlibGraphicCmd, - lifespan: PieceLifespan.WithinPart, - content: { - timelineObjects: config.studio.HTMLGraphics - ? [ - literal({ - id: '', - enable: { - start: 0, - duration: 1000 - }, - priority: 100, - layer: SharedGraphicLLayer.GraphicLLayerAdLibs, - content: { - deviceType: TSR.DeviceType.VIZMSE, - type: TSR.TimelineContentTypeVizMSE.CLEAR_ALL_ELEMENTS, - showId: config.selectedGraphicsSetup.OvlShowId - } - }) - ] - : [] - } - }) - ) + pieces.push({ + externalId: partId, + name: 'CLEAR', + ...CreateTimingEnable(parsedCue, GetDefaultOut(config)), + outputLayerId: SharedOutputLayers.SEC, + sourceLayerId: SourceLayer.PgmAdlibGraphicCmd, + lifespan: PieceLifespan.WithinPart, + content: { + timelineObjects: config.studio.HTMLGraphics + ? [ + literal({ + id: '', + enable: { + start: 0, + duration: 1000 + }, + priority: 100, + layer: SharedGraphicLLayer.GraphicLLayerAdLibs, + content: { + deviceType: TSR.DeviceType.VIZMSE, + type: TSR.TimelineContentTypeVizMSE.CLEAR_ALL_ELEMENTS, + showId: config.selectedGraphicsSetup.OvlShowId + } + }) + ] + : [] + } + }) } diff --git a/src/tv2_afvd_showstyle/helpers/pieces/dve.ts b/src/tv2_afvd_showstyle/helpers/pieces/dve.ts index 46081decc..0a5e4ee7b 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/dve.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/dve.ts @@ -15,7 +15,6 @@ import { getUniquenessIdDVE, literal, PartDefinition, - PieceMetaData, TemplateIsValid } from 'tv2-common' import { AdlibActionType, SharedOutputLayers } from 'tv2-constants' @@ -62,7 +61,7 @@ export function EvaluateDVE( if (content.valid) { if (adlib) { adlibPieces.push( - literal({ + literal>({ _rank: rank || 0, externalId: partDefinition.externalId, name: `${partDefinition.storyName} DVE: ${parsedCue.template}`, @@ -73,7 +72,7 @@ export function EvaluateDVE( toBeQueued: true, content: content.content, prerollDuration: Number(config.studio.CasparPrerollDuration) || 0, - metaData: literal({ + metaData: { sources: parsedCue.sources, config: rawTemplate, userData: literal({ @@ -85,7 +84,7 @@ export function EvaluateDVE( sisyfosPersistMetaData: { sisyfosLayers: [] } - }) + } }) ) } else { @@ -93,7 +92,7 @@ export function EvaluateDVE( start = start ? start : 0 const end = parsedCue.end ? CalculateTime(parsedCue.end) : undefined pieces.push( - literal({ + literal>({ externalId: partDefinition.externalId, name: `DVE: ${parsedCue.template}`, enable: { @@ -106,20 +105,20 @@ export function EvaluateDVE( toBeQueued: true, content: content.content, prerollDuration: Number(config.studio.CasparPrerollDuration) || 0, - metaData: literal({ + metaData: { mediaPlayerSessions: [partDefinition.segmentExternalId], sources: parsedCue.sources, config: rawTemplate, - userData: literal({ + userData: { type: AdlibActionType.SELECT_DVE, config: parsedCue, videoId: partDefinition.fields.videoId, segmentExternalId: partDefinition.segmentExternalId - }), + }, sisyfosPersistMetaData: { sisyfosLayers: [] } - }) + } }) ) } diff --git a/src/tv2_afvd_showstyle/helpers/pieces/ekstern.ts b/src/tv2_afvd_showstyle/helpers/pieces/ekstern.ts index f986e38e3..ac382dc39 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/ekstern.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/ekstern.ts @@ -5,7 +5,13 @@ import { IBlueprintPiece, ISegmentUserContext } from '@tv2media/blueprints-integration' -import { CueDefinitionEkstern, EvaluateEksternBase, PartDefinition, TV2BlueprintConfig } from 'tv2-common' +import { + CueDefinitionEkstern, + EvaluateEksternBase, + PartDefinition, + PieceMetaData, + TV2BlueprintConfig +} from 'tv2-common' import { AtemLLayer } from '../../../tv2_afvd_studio/layers' import { SourceLayer } from '../../layers' @@ -13,8 +19,8 @@ export function EvaluateEkstern( context: ISegmentUserContext, config: TV2BlueprintConfig, part: IBlueprintPart, - pieces: IBlueprintPiece[], - adlibPieces: IBlueprintAdLibPiece[], + pieces: Array>, + adlibPieces: Array>, _actions: IBlueprintActionManifest[], partId: string, parsedCue: CueDefinitionEkstern, diff --git a/src/tv2_afvd_showstyle/helpers/pieces/graphic.ts b/src/tv2_afvd_showstyle/helpers/pieces/graphic.ts index d570349d6..dbd656b19 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/graphic.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/graphic.ts @@ -33,7 +33,7 @@ export function EvaluateCueGraphic( } if (GraphicIsInternal(parsedCue)) { - CreateInternalGraphic(config, context, pieces, adlibPieces, actions, partId, parsedCue, partDefinition, adlib) + CreateInternalGraphic(config, context, pieces, adlibPieces, partId, parsedCue, partDefinition, adlib) } else if (GraphicIsPilot(parsedCue)) { EvaluateCueGraphicPilot( config, diff --git a/src/tv2_afvd_showstyle/helpers/pieces/graphicBackgroundLoop.ts b/src/tv2_afvd_showstyle/helpers/pieces/graphicBackgroundLoop.ts index 944e0626e..3e39ff3de 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/graphicBackgroundLoop.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/graphicBackgroundLoop.ts @@ -28,80 +28,72 @@ export function EvaluateCueBackgroundLoop( const fileName = parsedCue.backgroundLoop const path = `dve/${fileName}` if (adlib) { - adlibPieces.push( - literal({ - _rank: rank || 0, - externalId: partId, - name: fileName, - outputLayerId: SharedOutputLayers.SEC, - sourceLayerId: SourceLayer.PgmDVEBackground, - lifespan: PieceLifespan.OutOnShowStyleEnd, - content: literal>({ - fileName, - path, - ignoreMediaObjectStatus: true, - timelineObjects: dveLoopTimeline(path) - }) + adlibPieces.push({ + _rank: rank || 0, + externalId: partId, + name: fileName, + outputLayerId: SharedOutputLayers.SEC, + sourceLayerId: SourceLayer.PgmDVEBackground, + lifespan: PieceLifespan.OutOnShowStyleEnd, + content: literal>({ + fileName, + path, + ignoreMediaObjectStatus: true, + timelineObjects: dveLoopTimeline(path) }) - ) + }) } else { - pieces.push( - literal({ - externalId: partId, - name: fileName, - enable: { - start - }, - outputLayerId: SharedOutputLayers.SEC, - sourceLayerId: SourceLayer.PgmDVEBackground, - lifespan: PieceLifespan.OutOnShowStyleEnd, - content: literal>({ - fileName, - path, - ignoreMediaObjectStatus: true, - timelineObjects: dveLoopTimeline(path) - }) + pieces.push({ + externalId: partId, + name: fileName, + enable: { + start + }, + outputLayerId: SharedOutputLayers.SEC, + sourceLayerId: SourceLayer.PgmDVEBackground, + lifespan: PieceLifespan.OutOnShowStyleEnd, + content: literal>({ + fileName, + path, + ignoreMediaObjectStatus: true, + timelineObjects: dveLoopTimeline(path) }) - ) + }) } } else { // Full if (adlib) { - adlibPieces.push( - literal({ - _rank: rank || 0, - externalId: partId, - name: parsedCue.backgroundLoop, - outputLayerId: SharedOutputLayers.SEC, - sourceLayerId: SourceLayer.PgmFullBackground, - lifespan: PieceLifespan.OutOnShowStyleEnd, - content: literal>({ - fileName: parsedCue.backgroundLoop, - path: parsedCue.backgroundLoop, - ignoreMediaObjectStatus: true, - timelineObjects: fullLoopTimeline(config, parsedCue) - }) + adlibPieces.push({ + _rank: rank || 0, + externalId: partId, + name: parsedCue.backgroundLoop, + outputLayerId: SharedOutputLayers.SEC, + sourceLayerId: SourceLayer.PgmFullBackground, + lifespan: PieceLifespan.OutOnShowStyleEnd, + content: literal>({ + fileName: parsedCue.backgroundLoop, + path: parsedCue.backgroundLoop, + ignoreMediaObjectStatus: true, + timelineObjects: fullLoopTimeline(config, parsedCue) }) - ) + }) } else { - pieces.push( - literal({ - externalId: partId, - name: parsedCue.backgroundLoop, - enable: { - start - }, - outputLayerId: SharedOutputLayers.SEC, - sourceLayerId: SourceLayer.PgmFullBackground, - lifespan: PieceLifespan.OutOnShowStyleEnd, - content: literal>({ - fileName: parsedCue.backgroundLoop, - path: parsedCue.backgroundLoop, - ignoreMediaObjectStatus: true, - timelineObjects: fullLoopTimeline(config, parsedCue) - }) + pieces.push({ + externalId: partId, + name: parsedCue.backgroundLoop, + enable: { + start + }, + outputLayerId: SharedOutputLayers.SEC, + sourceLayerId: SourceLayer.PgmFullBackground, + lifespan: PieceLifespan.OutOnShowStyleEnd, + content: literal>({ + fileName: parsedCue.backgroundLoop, + path: parsedCue.backgroundLoop, + ignoreMediaObjectStatus: true, + timelineObjects: fullLoopTimeline(config, parsedCue) }) - ) + }) } } } diff --git a/src/tv2_afvd_showstyle/helpers/pieces/jingle.ts b/src/tv2_afvd_showstyle/helpers/pieces/jingle.ts index 4aaf7057c..706c6b3f9 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/jingle.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/jingle.ts @@ -12,7 +12,6 @@ import { generateExternalId, GetTagForJingle, GetTagForJingleNext, - literal, PartDefinition, t, TimeFromFrames @@ -52,61 +51,57 @@ export function EvaluateJingle( } if (adlib) { - const userData = literal({ + const userData: ActionSelectJingle = { type: AdlibActionType.SELECT_JINGLE, clip: parsedCue.clip, segmentExternalId: part.segmentExternalId + } + actions.push({ + externalId: generateExternalId(context, userData), + actionId: AdlibActionType.SELECT_JINGLE, + userData, + userDataManifest: {}, + display: { + _rank: rank ?? 0, + label: t(effekt ? `EFFEKT ${parsedCue.clip}` : parsedCue.clip), + sourceLayerId: SourceLayer.PgmJingle, + outputLayerId: SharedOutputLayers.JINGLE, + content: { + ...createJingleContentAFVD( + config, + file, + jingle.StartAlpha, + jingle.LoadFirstFrame, + jingle.Duration, + jingle.EndAlpha + ) + }, + tags: [AdlibTags.ADLIB_FLOW_PRODUCER], + currentPieceTags: [GetTagForJingle(part.segmentExternalId, parsedCue.clip)], + nextPieceTags: [GetTagForJingleNext(part.segmentExternalId, parsedCue.clip)] + } }) - actions.push( - literal({ - externalId: generateExternalId(context, userData), - actionId: AdlibActionType.SELECT_JINGLE, - userData, - userDataManifest: {}, - display: { - _rank: rank ?? 0, - label: t(effekt ? `EFFEKT ${parsedCue.clip}` : parsedCue.clip), - sourceLayerId: SourceLayer.PgmJingle, - outputLayerId: SharedOutputLayers.JINGLE, - content: { - ...createJingleContentAFVD( - config, - file, - jingle.StartAlpha, - jingle.LoadFirstFrame, - jingle.Duration, - jingle.EndAlpha - ) - }, - tags: [AdlibTags.ADLIB_FLOW_PRODUCER], - currentPieceTags: [GetTagForJingle(part.segmentExternalId, parsedCue.clip)], - nextPieceTags: [GetTagForJingleNext(part.segmentExternalId, parsedCue.clip)] - } - }) - ) } else { - pieces.push( - literal({ - externalId: `${part.externalId}-JINGLE`, - name: effekt ? `EFFEKT ${parsedCue.clip}` : parsedCue.clip, - enable: { - start: 0 - }, - lifespan: PieceLifespan.WithinPart, - outputLayerId: SharedOutputLayers.JINGLE, - sourceLayerId: SourceLayer.PgmJingle, - prerollDuration: config.studio.CasparPrerollDuration + TimeFromFrames(Number(jingle.StartAlpha)), - tags: [!effekt ? TallyTags.JINGLE : ''], - content: createJingleContentAFVD( - config, - file, - jingle.StartAlpha, - jingle.LoadFirstFrame, - jingle.Duration, - jingle.EndAlpha - ) - }) - ) + pieces.push({ + externalId: `${part.externalId}-JINGLE`, + name: effekt ? `EFFEKT ${parsedCue.clip}` : parsedCue.clip, + enable: { + start: 0 + }, + lifespan: PieceLifespan.WithinPart, + outputLayerId: SharedOutputLayers.JINGLE, + sourceLayerId: SourceLayer.PgmJingle, + prerollDuration: config.studio.CasparPrerollDuration + TimeFromFrames(Number(jingle.StartAlpha)), + tags: [!effekt ? TallyTags.JINGLE : ''], + content: createJingleContentAFVD( + config, + file, + jingle.StartAlpha, + jingle.LoadFirstFrame, + jingle.Duration, + jingle.EndAlpha + ) + }) } } @@ -118,7 +113,7 @@ export function createJingleContentAFVD( duration: number, alphaAtEnd: number ) { - const content = CreateJingleContentBase(config, file, alphaAtStart, loadFirstFrame, duration, alphaAtEnd, { + return CreateJingleContentBase(config, file, alphaAtStart, loadFirstFrame, duration, alphaAtEnd, { Caspar: { PlayerJingle: CasparLLayer.CasparPlayerJingle }, @@ -129,6 +124,4 @@ export function createJingleContentAFVD( PlayerJingle: SisyfosLLAyer.SisyfosSourceJingle } }) - - return content } diff --git a/src/tv2_afvd_showstyle/helpers/pieces/routing.ts b/src/tv2_afvd_showstyle/helpers/pieces/routing.ts index 64dda92f1..cf116a812 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/routing.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/routing.ts @@ -37,35 +37,33 @@ export function EvaluateCueRouting( return } - pieces.push( - literal({ - externalId: partId, - enable: { - start: time - }, - name, - outputLayerId: SharedOutputLayers.AUX, - sourceLayerId: SourceLayer.VizFullIn1, - lifespan: PieceLifespan.WithinPart, - content: literal>({ - studioLabel: '', - switcherInput: sourceInfo.port, - timelineObjects: _.compact([ - literal({ - id: '', - enable: { start: 0 }, - priority: 100, - layer: AtemLLayer.AtemAuxVizOvlIn1, - content: { - deviceType: TSR.DeviceType.ATEM, - type: TSR.TimelineContentTypeAtem.AUX, - aux: { - input: sourceInfo.port - } + pieces.push({ + externalId: partId, + enable: { + start: time + }, + name, + outputLayerId: SharedOutputLayers.AUX, + sourceLayerId: SourceLayer.VizFullIn1, + lifespan: PieceLifespan.WithinPart, + content: literal>({ + studioLabel: '', + switcherInput: sourceInfo.port, + timelineObjects: _.compact([ + literal({ + id: '', + enable: { start: 0 }, + priority: 100, + layer: AtemLLayer.AtemAuxVizOvlIn1, + content: { + deviceType: TSR.DeviceType.ATEM, + type: TSR.TimelineContentTypeAtem.AUX, + aux: { + input: sourceInfo.port } - }) - ]) - }) + } + }) + ]) }) - ) + }) } diff --git a/src/tv2_afvd_showstyle/helpers/pieces/showLifecycle.ts b/src/tv2_afvd_showstyle/helpers/pieces/showLifecycle.ts index c5f647e2e..691b2c59b 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/showLifecycle.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/showLifecycle.ts @@ -1,4 +1,4 @@ -import { BlueprintResultPart, IBlueprintPiece, PieceLifespan, TSR } from '@tv2media/blueprints-integration' +import { BlueprintResultPart, PieceLifespan, TSR } from '@tv2media/blueprints-integration' import { literal, TV2BlueprintConfig } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' import { GraphicLLayer } from '../../../tv2_afvd_studio/layers' @@ -11,43 +11,41 @@ export function CreateShowLifecyclePieces( cleanupShowIds: string[] ) { if (config.studio.GraphicsType === 'VIZ') { - part.pieces.push( - literal({ - externalId: part.part.externalId, - name: 'GFX Show Init', - enable: { start: 0 }, - outputLayerId: SharedOutputLayers.SEC, - sourceLayerId: SourceLayer.GraphicsShowLifecycle, - lifespan: PieceLifespan.OutOnSegmentChange, - content: { - timelineObjects: [ - literal({ - id: '', - enable: { - while: '1' - }, - layer: GraphicLLayer.GraphicLLayerInitialize, - content: { - deviceType: TSR.DeviceType.VIZMSE, - type: TSR.TimelineContentTypeVizMSE.INITIALIZE_SHOWS, - showIds: initializeShowIds - } - }), - literal({ - id: '', - enable: { - while: '1' - }, - layer: GraphicLLayer.GraphicLLayerCleanup, - content: { - deviceType: TSR.DeviceType.VIZMSE, - type: TSR.TimelineContentTypeVizMSE.CLEANUP_SHOWS, - showIds: cleanupShowIds - } - }) - ] - } - }) - ) + part.pieces.push({ + externalId: part.part.externalId, + name: 'GFX Show Init', + enable: { start: 0 }, + outputLayerId: SharedOutputLayers.SEC, + sourceLayerId: SourceLayer.GraphicsShowLifecycle, + lifespan: PieceLifespan.OutOnSegmentChange, + content: { + timelineObjects: [ + literal({ + id: '', + enable: { + while: '1' + }, + layer: GraphicLLayer.GraphicLLayerInitialize, + content: { + deviceType: TSR.DeviceType.VIZMSE, + type: TSR.TimelineContentTypeVizMSE.INITIALIZE_SHOWS, + showIds: initializeShowIds + } + }), + literal({ + id: '', + enable: { + while: '1' + }, + layer: GraphicLLayer.GraphicLLayerCleanup, + content: { + deviceType: TSR.DeviceType.VIZMSE, + type: TSR.TimelineContentTypeVizMSE.CLEANUP_SHOWS, + showIds: cleanupShowIds + } + }) + ] + } + }) } } diff --git a/src/tv2_afvd_showstyle/migrations/index.ts b/src/tv2_afvd_showstyle/migrations/index.ts index 4cd3ae33f..302146dc7 100644 --- a/src/tv2_afvd_showstyle/migrations/index.ts +++ b/src/tv2_afvd_showstyle/migrations/index.ts @@ -4,7 +4,6 @@ import { changeGFXTemplate, GetDefaultAdLibTriggers, GetDSKSourceLayerNames, - literal, RemoveOldShortcuts, removeSourceLayer, SetShowstyleTransitionMigrationStep, @@ -15,7 +14,6 @@ import { UpsertValuesIntoTransitionTable } from 'tv2-common' import { SharedGraphicLLayer } from 'tv2-constants' -import * as _ from 'underscore' import { remapVizDOvl, remapVizLLayer } from '../../tv2_offtube_showstyle/migrations' import { remapTableColumnValues } from '../../tv2_offtube_showstyle/migrations/util' import { ATEMModel } from '../../types/atem' @@ -38,7 +36,7 @@ const SHOW_STYLE_ID = 'tv2_afvd_showstyle' * 0.1.0: Core 0.24.0 */ -export const showStyleMigrations: MigrationStepShowStyle[] = literal([ +export const showStyleMigrations: MigrationStepShowStyle[] = [ ...getCreateVariantMigrationSteps(), ...remapTableColumnValues('0.1.0', 'GFXTemplates', 'LayerMapping', remapVizLLayer), // Rename "viz-d-ovl" to "OVL1" @@ -119,7 +117,7 @@ export const showStyleMigrations: MigrationStepShowStyle[] = literal { - return literal({ + return { id: `${versionStr}.sourcelayer.defaults${force ? '.forced' : ''}.${defaultVal._id}`, version: versionStr, canBeRunAutomatically: true, @@ -38,7 +38,7 @@ export function getSourceLayerDefaultsMigrationSteps(versionStr: string, force?: context.insertSourceLayer(defaultVal._id, defaultVal) } } - }) + } }) ) } @@ -52,7 +52,7 @@ export function forceSourceLayerToDefaults( } export function forceSettingToDefaults(versionStr: string, setting: string): MigrationStepShowStyle { - return literal({ + return { id: `${versionStr}.sourcelayer.defaults.${setting}.forced`, version: versionStr, canBeRunAutomatically: true, @@ -85,7 +85,7 @@ export function forceSettingToDefaults(versionStr: string, setting: string): Mig context.setBaseConfig(setting, defaultVal.defaultVal) } } - }) + } } export function getOutputLayerDefaultsMigrationSteps(versionStr: string): MigrationStepShowStyle[] { diff --git a/src/tv2_afvd_showstyle/parts/cueonly.ts b/src/tv2_afvd_showstyle/parts/cueonly.ts index 22eced5db..c378d7fb9 100644 --- a/src/tv2_afvd_showstyle/parts/cueonly.ts +++ b/src/tv2_afvd_showstyle/parts/cueonly.ts @@ -12,7 +12,6 @@ import { CueDefinition, GetJinglePartProperties, GraphicIsPilot, - literal, PartDefinition, PartTime } from 'tv2-common' @@ -34,11 +33,11 @@ export async function CreatePartCueOnly( const partDefinitionWithID = { ...partDefinition, ...{ externalId: id } } const partTime = PartTime(config, partDefinitionWithID, totalWords, false) - let part = literal({ + let part: IBlueprintPart = { externalId: id, title, metaData: {} - }) + } const adLibPieces: IBlueprintAdLibPiece[] = [] const pieces: IBlueprintPiece[] = [] diff --git a/src/tv2_afvd_showstyle/parts/evs.ts b/src/tv2_afvd_showstyle/parts/evs.ts index d5f8d3a8f..b2ab05004 100644 --- a/src/tv2_afvd_showstyle/parts/evs.ts +++ b/src/tv2_afvd_showstyle/parts/evs.ts @@ -39,15 +39,15 @@ export async function CreatePartEVS( const partTime = PartTime(config, partDefinition, totalWords, false) const title = partDefinition.sourceDefinition.name - let part = literal({ + let part: IBlueprintPart = { externalId: partDefinition.externalId, title, metaData: {}, expectedDuration: partTime > 0 ? partTime : 0 - }) + } const adLibPieces: IBlueprintAdLibPiece[] = [] - const pieces: IBlueprintPiece[] = [] + const pieces: Array> = [] const actions: IBlueprintActionManifest[] = [] const mediaSubscriptions: HackPartMediaObjectSubscription[] = [] @@ -59,22 +59,20 @@ export async function CreatePartEVS( } const atemInput = sourceInfoReplay.port - pieces.push( - literal({ - externalId: partDefinition.externalId, - name: part.title, - enable: { start: 0 }, - outputLayerId: SharedOutputLayers.PGM, - sourceLayerId: SourceLayer.PgmLocal, - lifespan: PieceLifespan.WithinPart, - metaData: literal({ - sisyfosPersistMetaData: { - sisyfosLayers: [] - } - }), - content: makeContentEVS(config, atemInput, partDefinition, sourceInfoReplay) - }) - ) + pieces.push({ + externalId: partDefinition.externalId, + name: part.title, + enable: { start: 0 }, + outputLayerId: SharedOutputLayers.PGM, + sourceLayerId: SourceLayer.PgmLocal, + lifespan: PieceLifespan.WithinPart, + metaData: { + sisyfosPersistMetaData: { + sisyfosLayers: [] + } + }, + content: makeContentEVS(config, atemInput, partDefinition, sourceInfoReplay) + }) await EvaluateCues( context, diff --git a/src/tv2_afvd_showstyle/parts/grafik.ts b/src/tv2_afvd_showstyle/parts/grafik.ts index 36c6989ad..23b2121d1 100644 --- a/src/tv2_afvd_showstyle/parts/grafik.ts +++ b/src/tv2_afvd_showstyle/parts/grafik.ts @@ -7,14 +7,7 @@ import { IBlueprintPiece, ISegmentUserContext } from '@tv2media/blueprints-integration' -import { - AddScript, - ApplyFullGraphicPropertiesToPart, - GraphicIsPilot, - literal, - PartDefinition, - PartTime -} from 'tv2-common' +import { AddScript, ApplyFullGraphicPropertiesToPart, GraphicIsPilot, PartDefinition, PartTime } from 'tv2-common' import { CueType } from 'tv2-constants' import { BlueprintConfig } from '../helpers/config' import { EvaluateCues } from '../helpers/pieces/evaluateCues' @@ -27,11 +20,11 @@ export async function CreatePartGrafik( totalWords: number ): Promise { const partTime = PartTime(config, partDefinition, totalWords, false) - const part = literal({ + const part: IBlueprintPart = { externalId: partDefinition.externalId, title: partDefinition.type + ' - ' + partDefinition.rawType, metaData: {} - }) + } const adLibPieces: IBlueprintAdLibPiece[] = [] const pieces: IBlueprintPiece[] = [] diff --git a/src/tv2_afvd_showstyle/parts/intro.ts b/src/tv2_afvd_showstyle/parts/intro.ts index 9e41d554c..d62a2c4a6 100644 --- a/src/tv2_afvd_showstyle/parts/intro.ts +++ b/src/tv2_afvd_showstyle/parts/intro.ts @@ -12,7 +12,6 @@ import { CreatePartInvalid, CueDefinitionJingle, GetJinglePartProperties, - literal, PartDefinition, PartTime } from 'tv2-common' @@ -61,11 +60,11 @@ export async function CreatePartIntro( return CreatePartInvalid(partDefinition) } - let part = literal({ + let part: IBlueprintPart = { externalId: partDefinition.externalId, title: partDefinition.type + ' - ' + partDefinition.rawType, metaData: {} - }) + } const adLibPieces: IBlueprintAdLibPiece[] = [] const pieces: IBlueprintPiece[] = [] diff --git a/src/tv2_afvd_showstyle/parts/kam.ts b/src/tv2_afvd_showstyle/parts/kam.ts index 5ba468003..c280c73bf 100644 --- a/src/tv2_afvd_showstyle/parts/kam.ts +++ b/src/tv2_afvd_showstyle/parts/kam.ts @@ -45,52 +45,50 @@ export async function CreatePartKam( const partTime = partKamBase.duration const adLibPieces: IBlueprintAdLibPiece[] = [] - const pieces: IBlueprintPiece[] = [] + const pieces: Array> = [] const actions: IBlueprintActionManifest[] = [] const mediaSubscriptions: HackPartMediaObjectSubscription[] = [] const jingleDSK = FindDSKJingle(config) if (partDefinition.rawType.match(/kam cs ?3/i)) { - pieces.push( - literal({ - externalId: partDefinition.externalId, - name: 'CS 3 (JINGLE)', - enable: { start: 0 }, - outputLayerId: SharedOutputLayers.PGM, - sourceLayerId: SourceLayer.PgmJingle, - lifespan: PieceLifespan.WithinPart, - metaData: literal({ - sisyfosPersistMetaData: { - sisyfosLayers: [] - } - }), - content: literal>({ - ignoreMediaObjectStatus: true, - fileName: '', - path: '', - timelineObjects: literal([ - literal({ - id: ``, - enable: { - start: 0 - }, - priority: 1, - layer: AtemLLayer.AtemMEProgram, - content: { - deviceType: TSR.DeviceType.ATEM, - type: TSR.TimelineContentTypeAtem.ME, - me: { - input: jingleDSK.Fill, - transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, - transitionSettings: TransitionSettings(config, partDefinition) - } + pieces.push({ + externalId: partDefinition.externalId, + name: 'CS 3 (JINGLE)', + enable: { start: 0 }, + outputLayerId: SharedOutputLayers.PGM, + sourceLayerId: SourceLayer.PgmJingle, + lifespan: PieceLifespan.WithinPart, + metaData: { + sisyfosPersistMetaData: { + sisyfosLayers: [] + } + }, + content: literal>({ + ignoreMediaObjectStatus: true, + fileName: '', + path: '', + timelineObjects: literal([ + literal({ + id: ``, + enable: { + start: 0 + }, + priority: 1, + layer: AtemLLayer.AtemMEProgram, + content: { + deviceType: TSR.DeviceType.ATEM, + type: TSR.TimelineContentTypeAtem.ME, + me: { + input: jingleDSK.Fill, + transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, + transitionSettings: TransitionSettings(config, partDefinition) } - }) - ]) - }) + } + }) + ]) }) - ) + }) part.expectedDuration = TimeFromINewsField(partDefinition.fields.totalTime) * 1000 } else { const sourceInfoCam = findSourceInfo(config.sources, partDefinition.sourceDefinition) @@ -102,49 +100,47 @@ export async function CreatePartKam( part = { ...part, ...CreateEffektForpart(context, config, partDefinition, pieces) } - pieces.push( - literal({ - externalId: partDefinition.externalId, - name: part.title, - enable: { start: 0 }, - outputLayerId: SharedOutputLayers.PGM, - sourceLayerId: SourceLayer.PgmCam, - lifespan: PieceLifespan.WithinPart, - metaData: literal({ - sisyfosPersistMetaData: { - sisyfosLayers: sourceInfoCam.sisyfosLayers ?? [], - acceptPersistAudio: sourceInfoCam.acceptPersistAudio - } - }), - content: { - studioLabel: '', - switcherInput: atemInput, - timelineObjects: literal([ - literal({ - id: ``, - enable: { - start: 0 - }, - priority: 1, - layer: AtemLLayer.AtemMEProgram, - content: { - deviceType: TSR.DeviceType.ATEM, - type: TSR.TimelineContentTypeAtem.ME, - me: { - input: Number(atemInput), - transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, - transitionSettings: TransitionSettings(config, partDefinition) - } - }, - ...(AddParentClass(config, partDefinition) - ? { classes: [CameraParentClass('studio0', partDefinition.sourceDefinition.id)] } - : {}) - }), - ...GetSisyfosTimelineObjForCamera(config, sourceInfoCam, partDefinition.sourceDefinition.minusMic) - ]) + pieces.push({ + externalId: partDefinition.externalId, + name: part.title, + enable: { start: 0 }, + outputLayerId: SharedOutputLayers.PGM, + sourceLayerId: SourceLayer.PgmCam, + lifespan: PieceLifespan.WithinPart, + metaData: { + sisyfosPersistMetaData: { + sisyfosLayers: sourceInfoCam.sisyfosLayers ?? [], + acceptPersistAudio: sourceInfoCam.acceptPersistAudio } - }) - ) + }, + content: { + studioLabel: '', + switcherInput: atemInput, + timelineObjects: literal([ + literal({ + id: ``, + enable: { + start: 0 + }, + priority: 1, + layer: AtemLLayer.AtemMEProgram, + content: { + deviceType: TSR.DeviceType.ATEM, + type: TSR.TimelineContentTypeAtem.ME, + me: { + input: Number(atemInput), + transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, + transitionSettings: TransitionSettings(config, partDefinition) + } + }, + ...(AddParentClass(config, partDefinition) + ? { classes: [CameraParentClass('studio0', partDefinition.sourceDefinition.id)] } + : {}) + }), + ...GetSisyfosTimelineObjForCamera(config, sourceInfoCam, partDefinition.sourceDefinition.minusMic) + ]) + } + }) } await EvaluateCues( diff --git a/src/tv2_afvd_showstyle/parts/live.ts b/src/tv2_afvd_showstyle/parts/live.ts index 958f95a15..6da5eb433 100644 --- a/src/tv2_afvd_showstyle/parts/live.ts +++ b/src/tv2_afvd_showstyle/parts/live.ts @@ -7,7 +7,7 @@ import { IBlueprintPiece, ISegmentUserContext } from '@tv2media/blueprints-integration' -import { AddScript, CueDefinitionEkstern, literal, PartDefinition, PartTime } from 'tv2-common' +import { AddScript, CueDefinitionEkstern, PartDefinition, PartTime } from 'tv2-common' import { CueType } from 'tv2-constants' import { BlueprintConfig } from '../../tv2_afvd_showstyle/helpers/config' import { EvaluateCues } from '../helpers/pieces/evaluateCues' @@ -21,12 +21,12 @@ export async function CreatePartLive( totalWords: number ): Promise { const partTime = PartTime(config, partDefinition, totalWords, false) - let part = literal({ + let part: IBlueprintPart = { externalId: partDefinition.externalId, title: partDefinition.title || 'Ekstern', metaData: {}, expectedDuration: partTime > 0 ? partTime : 0 - }) + } const adLibPieces: IBlueprintAdLibPiece[] = [] const pieces: IBlueprintPiece[] = [] diff --git a/src/tv2_afvd_showstyle/parts/teknik.ts b/src/tv2_afvd_showstyle/parts/teknik.ts index 42708b0ba..f93bd2386 100644 --- a/src/tv2_afvd_showstyle/parts/teknik.ts +++ b/src/tv2_afvd_showstyle/parts/teknik.ts @@ -7,7 +7,7 @@ import { IBlueprintPiece, ISegmentUserContext } from '@tv2media/blueprints-integration' -import { AddScript, literal, PartDefinition, PartTime } from 'tv2-common' +import { AddScript, PartDefinition, PartTime } from 'tv2-common' import { BlueprintConfig } from '../helpers/config' import { EvaluateCues } from '../helpers/pieces/evaluateCues' import { SourceLayer } from '../layers' @@ -19,11 +19,11 @@ export async function CreatePartTeknik( totalWords: number ): Promise { const partTime = PartTime(config, partDefinition, totalWords, false) - const part = literal({ + const part: IBlueprintPart = { externalId: partDefinition.externalId, title: partDefinition.type + ' - ' + partDefinition.rawType, metaData: {} - }) + } const adLibPieces: IBlueprintAdLibPiece[] = [] const pieces: IBlueprintPiece[] = [] diff --git a/src/tv2_afvd_showstyle/parts/unknown.ts b/src/tv2_afvd_showstyle/parts/unknown.ts index eb79c1164..6f991fbe2 100644 --- a/src/tv2_afvd_showstyle/parts/unknown.ts +++ b/src/tv2_afvd_showstyle/parts/unknown.ts @@ -11,7 +11,6 @@ import { ApplyFullGraphicPropertiesToPart, GetJinglePartProperties, GraphicIsPilot, - literal, PartDefinition, PartTime } from 'tv2-common' @@ -30,13 +29,13 @@ export async function CreatePartUnknown( ) { const partTime = PartTime(config, partDefinition, totalWords, false) - let part = literal({ + let part: IBlueprintPart = { externalId: partDefinition.externalId, title: partDefinition.type + ' - ' + partDefinition.rawType, metaData: {}, autoNext: false, expectedDuration: partTime - }) + } const adLibPieces: IBlueprintAdLibPiece[] = [] const pieces: IBlueprintPiece[] = [] diff --git a/src/tv2_afvd_showstyle/postProcessTimelineObjects.ts b/src/tv2_afvd_showstyle/postProcessTimelineObjects.ts index be5274fb8..14ace1ff0 100644 --- a/src/tv2_afvd_showstyle/postProcessTimelineObjects.ts +++ b/src/tv2_afvd_showstyle/postProcessTimelineObjects.ts @@ -9,7 +9,7 @@ import { TimelineObjHoldMode, TSR } from '@tv2media/blueprints-integration' -import { AtemLLayerDSK, FindDSKJingle, literal, TimelineBlueprintExt } from 'tv2-common' +import { AtemLLayerDSK, FindDSKJingle, TimelineBlueprintExt } from 'tv2-common' import * as _ from 'underscore' import { AtemLLayer } from '../tv2_afvd_studio/layers' import { BlueprintConfig } from './helpers/config' @@ -72,7 +72,7 @@ export function postProcessPieceTimelineObjects( (tlObj.content.me.input !== -1 || tlObj.metaData?.mediaPlayerSession !== undefined) ) { // Create a lookahead-lookahead object for this me-program - const lookaheadObj = literal({ + const lookaheadObj: TSR.TimelineObjAtemAUX & TimelineBlueprintExt = { id: '', enable: { start: 0 }, priority: tlObj.holdMode === TimelineObjHoldMode.ONLY ? 5 : 0, // Must be below lookahead, except when forced by hold @@ -92,7 +92,7 @@ export function postProcessPieceTimelineObjects( context: `Lookahead-lookahead for ${tlObj.id}`, mediaPlayerSession: tlObj.metaData?.mediaPlayerSession // TODO - does this work the same? } - }) + } extraObjs.push(lookaheadObj) } @@ -120,7 +120,7 @@ export function postProcessPieceTimelineObjects( mixMinusSource = kamSources.length === 1 ? Number(kamSources[0].switcherInput) : null } if (mixMinusSource !== null && mixMinusSource !== -1) { - const mixMinusObj = literal({ + const mixMinusObj: TSR.TimelineObjAtemAUX & TimelineBlueprintExt = { ..._.omit(tlObj, 'content'), id: '', layer: AtemLLayer.AtemAuxVideoMixMinus, @@ -139,7 +139,7 @@ export function postProcessPieceTimelineObjects( ...tlObj.metaData, context: `Mix-minus for ${tlObj.id}` } - }) + } mixMinusObj.classes = mixMinusObj.classes?.filter( c => !c.match(`studio0_parent_`) && !c.match('PLACEHOLDER_OBJECT_REMOVEME') ) @@ -161,7 +161,7 @@ export function postProcessPieceTimelineObjects( context.notifyUserWarning(`Unhandled Keyer properties for Clean keyer, it may look wrong`) } - const cleanObj = literal({ + const cleanObj: TSR.TimelineObjAtemME & TimelineBlueprintExt = { ..._.omit(tlObj, 'content', 'keyframes'), id: '', layer: AtemLLayer.AtemCleanUSKEffect, @@ -180,7 +180,7 @@ export function postProcessPieceTimelineObjects( ] } } - }) + } extraObjs.push(cleanObj) } }) diff --git a/src/tv2_afvd_studio/config-manifests.ts b/src/tv2_afvd_studio/config-manifests.ts index 710b48bc9..9998bbe39 100644 --- a/src/tv2_afvd_studio/config-manifests.ts +++ b/src/tv2_afvd_studio/config-manifests.ts @@ -12,7 +12,6 @@ import { MakeConfigWithMediaFlow, TableConfigItemSourceMapping } from 'tv2-common' -import * as _ from 'underscore' import { AtemSourceIndex } from '../types/atem' import { defaultDSKConfig } from './helpers/config' import { SisyfosLLAyer } from './layers' diff --git a/src/tv2_afvd_studio/getBaseline.ts b/src/tv2_afvd_studio/getBaseline.ts index 97604eb98..96220025b 100644 --- a/src/tv2_afvd_studio/getBaseline.ts +++ b/src/tv2_afvd_studio/getBaseline.ts @@ -11,7 +11,7 @@ import { SharedGraphicLLayer } from '../tv2-constants' import { AtemSourceIndex } from '../types/atem' import { getStudioConfig } from './helpers/config' import { AtemLLayer, SisyfosLLAyer } from './layers' -import { SisyfosChannel, sisyfosChannels } from './sisyfosChannels' +import { sisyfosChannels } from './sisyfosChannels' function filterMappings( input: BlueprintMappings, @@ -48,7 +48,7 @@ export function getBaseline(context: IStudioContext): BlueprintResultBaseline { const mappedChannels: TSR.TimelineObjSisyfosChannels['content']['channels'] = [] for (const id in sisyfosMappings) { if (sisyfosMappings[id]) { - const sisyfosChannel = sisyfosChannels[id as SisyfosLLAyer] as SisyfosChannel | undefined + const sisyfosChannel = sisyfosChannels[id as SisyfosLLAyer] if (sisyfosChannel) { mappedChannels.push({ mappedLayer: id, diff --git a/src/tv2_afvd_studio/helpers/config.ts b/src/tv2_afvd_studio/helpers/config.ts index 4403e269f..2eb9c2028 100644 --- a/src/tv2_afvd_studio/helpers/config.ts +++ b/src/tv2_afvd_studio/helpers/config.ts @@ -8,7 +8,6 @@ import { TV2StudioConfigBase } from 'tv2-common' import { DSKRoles } from 'tv2-constants' -import * as _ from 'underscore' import { ShowStyleConfig } from '../../tv2_afvd_showstyle/helpers/config' import { parseMediaPlayers, parseSources } from './sources' diff --git a/src/tv2_afvd_studio/migrations/devices.ts b/src/tv2_afvd_studio/migrations/devices.ts index d088ad397..ae375657d 100644 --- a/src/tv2_afvd_studio/migrations/devices.ts +++ b/src/tv2_afvd_studio/migrations/devices.ts @@ -5,7 +5,6 @@ import { MigrationStepStudio, TSR } from '@tv2media/blueprints-integration' -import { literal } from 'tv2-common' import * as _ from 'underscore' declare const VERSION: string // Injected by webpack @@ -218,10 +217,10 @@ const devices: DeviceEntry[] = [ } ] -export const deviceMigrations = literal([ +export const deviceMigrations: MigrationStepStudio[] = [ // create all devices ..._.map(devices, createDevice), // ensure all devices still look valid ..._.map(devices, validateDevice) -]) +] diff --git a/src/tv2_afvd_studio/migrations/index.ts b/src/tv2_afvd_studio/migrations/index.ts index e6b740d0f..421ec2d1a 100644 --- a/src/tv2_afvd_studio/migrations/index.ts +++ b/src/tv2_afvd_studio/migrations/index.ts @@ -2,7 +2,6 @@ import { MigrationStepStudio, TSR } from '@tv2media/blueprints-integration' import { AddKeepAudio, addSourceToSourcesConfig, - literal, MoveClipSourcePath, MoveSourcesToTable, PrefixEvsWithEvs, @@ -40,7 +39,7 @@ declare const VERSION: string // Injected by webpack * 0.1.0: Core 0.24.0 */ -export const studioMigrations: MigrationStepStudio[] = literal([ +export const studioMigrations: MigrationStepStudio[] = [ ensureStudioConfig( '0.1.0', 'SourcesCam', @@ -199,4 +198,4 @@ export const studioMigrations: MigrationStepStudio[] = literal { - return literal({ + return { id: `${versionStr}.mappings.defaults.${id}`, version: versionStr, canBeRunAutomatically: true, @@ -151,11 +150,9 @@ export function getMappingsDefaultsMigrationSteps(versionStr: string): Migration context.insertMapping(id, defaultVal) } } - }) + } }) ) - - return res } export function GetMappingDefaultMigrationStepForLayer( @@ -163,7 +160,7 @@ export function GetMappingDefaultMigrationStepForLayer( layer: string, force?: boolean ): MigrationStepStudio { - return literal({ + return { id: `${versionStr}.mappings.defaults.manualEnsure${layer}`, version: versionStr, canBeRunAutomatically: true, @@ -190,7 +187,7 @@ export function GetMappingDefaultMigrationStepForLayer( context.insertMapping(layer, MappingsDefaults[layer]) } } - }) + } } /** @@ -207,7 +204,7 @@ export function EnsureSisyfosMappingHasType( layer: string, mappingType: TSR.MappingSisyfosType.CHANNEL ): MigrationStepStudio { - return literal({ + return { id: `${versionStr}.mutatesisyfosmappings.${layer}`, version: versionStr, canBeRunAutomatically: true, @@ -237,7 +234,7 @@ export function EnsureSisyfosMappingHasType( context.updateMapping(layer, mapping) } - }) + } } export function GetSisyfosLayersForTableMigrationAFVD(configName: string, val: string): string[] { diff --git a/src/tv2_afvd_studio/onTimelineGenerate.ts b/src/tv2_afvd_studio/onTimelineGenerate.ts index 3b877ce3e..0cbd50c4a 100644 --- a/src/tv2_afvd_studio/onTimelineGenerate.ts +++ b/src/tv2_afvd_studio/onTimelineGenerate.ts @@ -6,8 +6,7 @@ import { PartEndState, TimelinePersistentState } from '@tv2media/blueprints-integration' -import { onTimelineGenerate } from 'tv2-common' -import * as _ from 'underscore' +import { onTimelineGenerate, PieceMetaData } from 'tv2-common' import { getConfig } from '../tv2_afvd_showstyle/helpers/config' import { AtemLLayer, CasparLLayer, SisyfosLLAyer } from './layers' @@ -16,7 +15,7 @@ export function onTimelineGenerateAFVD( timeline: OnGenerateTimelineObj[], previousPersistentState: TimelinePersistentState | undefined, previousPartEndState: PartEndState | undefined, - resolvedPieces: IBlueprintResolvedPieceInstance[] + resolvedPieces: Array> ): Promise { return onTimelineGenerate( context, diff --git a/src/tv2_offtube_showstyle/__tests__/actions.spec.ts b/src/tv2_offtube_showstyle/__tests__/actions.spec.ts index a009709c4..4714696ff 100644 --- a/src/tv2_offtube_showstyle/__tests__/actions.spec.ts +++ b/src/tv2_offtube_showstyle/__tests__/actions.spec.ts @@ -1,7 +1,6 @@ import { IBlueprintPartDB, IBlueprintPartInstance, - IBlueprintPieceDB, IBlueprintPieceInstance, PieceLifespan, TSR @@ -16,6 +15,7 @@ import { ActionTakeWithTransition, literal, PartDefinitionUnknown, + PieceMetaData, RemoteType, SourceDefinitionKam, SourceDefinitionRemote @@ -67,9 +67,9 @@ const currentPartMock: IBlueprintPartInstance = { rehearsal: false } -const kamPieceInstance: IBlueprintPieceInstance = { +const kamPieceInstance: IBlueprintPieceInstance = { _id: '', - piece: literal({ + piece: { _id: 'KAM 1', enable: { start: 0 @@ -98,13 +98,13 @@ const kamPieceInstance: IBlueprintPieceInstance = { }) ] } - }), + }, partInstanceId: '' } -const playingServerPieceInstance: IBlueprintPieceInstance = { +const playingServerPieceInstance: IBlueprintPieceInstance = { _id: '', - piece: literal({ + piece: { _id: 'Playing Server', enable: { start: 0 @@ -117,13 +117,13 @@ const playingServerPieceInstance: IBlueprintPieceInstance = { content: { timelineObjects: [] } - }), + }, partInstanceId: '' } -const selectedServerPieceInstance: IBlueprintPieceInstance = { +const selectedServerPieceInstance: IBlueprintPieceInstance = { _id: '', - piece: literal({ + piece: { _id: 'Selected Server', enable: { start: 0 @@ -136,7 +136,7 @@ const selectedServerPieceInstance: IBlueprintPieceInstance = { content: { timelineObjects: [] } - }), + }, partInstanceId: '' } @@ -371,7 +371,7 @@ function validateNextPartExistsWithPreviousPartKeepaliveDuration(context: Action } function getATEMMEObj(piece: IBlueprintPieceInstance): TSR.TimelineObjAtemME { - const atemObj = (piece.piece.content!.timelineObjects as TSR.TSRTimelineObj[]).find( + const atemObj = (piece.piece.content.timelineObjects as TSR.TSRTimelineObj[]).find( obj => obj.layer === OfftubeAtemLLayer.AtemMEClean && obj.content.deviceType === TSR.DeviceType.ATEM && @@ -556,39 +556,6 @@ describe('Combination Actions', () => { expect(voPieces.dataStore?.piece.name).toEqual('VOVOA') }) - it('Server -> DVE', async () => { - const context = new ActionExecutionContext( - 'test', - mappingsDefaults, - parseStudioConfig, - parseShowStyleConfig, - RUNDOWN_ID, - SEGMENT_ID, - currentPartMock._id, - currentPartMock, - [kamPieceInstance] - ) - context.studioConfig = defaultStudioConfig as any - context.showStyleConfig = defaultShowStyleConfig as any - ;((context.studioConfig as unknown) as OfftubeStudioConfig).GraphicsType = 'HTML' - - await executeActionOfftube(context, AdlibActionType.SELECT_SERVER_CLIP, selectServerClipAction) - - let serverPieces = await getActiveServerPieces(context, 'next') - - validateNextPartExistsWithDuration(context, SERVER_DURATION_A) - validateSourcePiecesExistWithPrerollDuration(serverPieces) - - await executeActionOfftube(context, AdlibActionType.SELECT_DVE, selectDVEActionMorbarn) - - serverPieces = await getActiveServerPieces(context, 'next') - const dvePieces = await getDVEPieces(context, 'next') - - validateNextPartExistsWithDuration(context, 0) - validateOnlySelectionIsPreserved(serverPieces) - validateSourcePiecesExistWithPrerollDuration(dvePieces) - }) - it('Server -> CAM', async () => { const context = new ActionExecutionContext( 'test', diff --git a/src/tv2_offtube_showstyle/cues/OfftubeAdlib.ts b/src/tv2_offtube_showstyle/cues/OfftubeAdlib.ts index ecd266d16..c3e76dd71 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeAdlib.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeAdlib.ts @@ -90,7 +90,7 @@ export async function OfftubeEvaluateAdLib( return } - if (!TemplateIsValid(rawTemplate.DVEJSON as string)) { + if (!TemplateIsValid(rawTemplate.DVEJSON)) { context.notifyUserWarning(`Invalid DVE template ${parsedCue.variant}`) return } @@ -105,30 +105,28 @@ export async function OfftubeEvaluateAdLib( const adlibContent = OfftubeMakeContentDVE(context, config, partDefinition, cueDVE, rawTemplate, false, true) - const userData = literal({ + const userData: ActionSelectDVE = { type: AdlibActionType.SELECT_DVE, config: cueDVE, videoId: partDefinition.fields.videoId, segmentExternalId: partDefinition.segmentExternalId + } + actions.push({ + externalId: generateExternalId(context, userData), + actionId: AdlibActionType.SELECT_DVE, + userData, + userDataManifest: {}, + display: { + sourceLayerId: OfftubeSourceLayer.PgmDVE, + outputLayerId: OfftubeOutputLayers.PGM, + uniquenessId: getUniquenessIdDVE(cueDVE), + label: t(`${partDefinition.storyName}`), + tags: [AdlibTags.ADLIB_KOMMENTATOR, AdlibTags.ADLIB_FLOW_PRODUCER], + content: literal({ + ...adlibContent.content + }) + } }) - actions.push( - literal({ - externalId: generateExternalId(context, userData), - actionId: AdlibActionType.SELECT_DVE, - userData, - userDataManifest: {}, - display: { - sourceLayerId: OfftubeSourceLayer.PgmDVE, - outputLayerId: OfftubeOutputLayers.PGM, - uniquenessId: getUniquenessIdDVE(cueDVE), - label: t(`${partDefinition.storyName}`), - tags: [AdlibTags.ADLIB_KOMMENTATOR, AdlibTags.ADLIB_FLOW_PRODUCER], - content: literal({ - ...adlibContent.content - }) - } - }) - ) } } diff --git a/src/tv2_offtube_showstyle/cues/OfftubeDVE.ts b/src/tv2_offtube_showstyle/cues/OfftubeDVE.ts index 86e808193..0f0501234 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeDVE.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeDVE.ts @@ -18,7 +18,6 @@ import { GetTagForDVENext, literal, PartDefinition, - PieceMetaData, t, TemplateIsValid } from 'tv2-common' @@ -77,70 +76,66 @@ export function OfftubeEvaluateDVE( let start = parsedCue.start ? CalculateTime(parsedCue.start) : 0 start = start ? start : 0 const end = parsedCue.end ? CalculateTime(parsedCue.end) : undefined - pieces.push( - literal({ - externalId: partDefinition.externalId, - name: `${parsedCue.template}`, - enable: { - start, - ...(end ? { duration: end - start } : {}) + pieces.push({ + externalId: partDefinition.externalId, + name: `${parsedCue.template}`, + enable: { + start, + ...(end ? { duration: end - start } : {}) + }, + outputLayerId: SharedOutputLayers.PGM, + sourceLayerId: OfftubeSourceLayer.PgmDVE, + lifespan: PieceLifespan.WithinPart, + toBeQueued: true, + content: { + ...pieceContent.content, + timelineObjects: [...pieceContent.content.timelineObjects] + }, + prerollDuration: Number(config.studio.CasparPrerollDuration) || 0, + metaData: literal({ + mediaPlayerSessions: [partDefinition.segmentExternalId], + sources: parsedCue.sources, + config: rawTemplate, + userData: { + type: AdlibActionType.SELECT_DVE, + config: parsedCue, + videoId: partDefinition.fields.videoId, + segmentExternalId: partDefinition.segmentExternalId }, - outputLayerId: SharedOutputLayers.PGM, - sourceLayerId: OfftubeSourceLayer.PgmDVE, - lifespan: PieceLifespan.WithinPart, - toBeQueued: true, - content: { - ...pieceContent.content, - timelineObjects: [...pieceContent.content.timelineObjects] - }, - prerollDuration: Number(config.studio.CasparPrerollDuration) || 0, - metaData: literal({ - mediaPlayerSessions: [partDefinition.segmentExternalId], - sources: parsedCue.sources, - config: rawTemplate, - userData: literal({ - type: AdlibActionType.SELECT_DVE, - config: parsedCue, - videoId: partDefinition.fields.videoId, - segmentExternalId: partDefinition.segmentExternalId - }), - sisyfosPersistMetaData: { - sisyfosLayers: [] - } - }), - tags: [ - GetTagForDVE(partDefinition.segmentExternalId, parsedCue.template, parsedCue.sources), - GetTagForDVENext(partDefinition.segmentExternalId, parsedCue.template, parsedCue.sources), - TallyTags.DVE_IS_LIVE - ] - }) - ) + sisyfosPersistMetaData: { + sisyfosLayers: [] + } + }), + tags: [ + GetTagForDVE(partDefinition.segmentExternalId, parsedCue.template, parsedCue.sources), + GetTagForDVENext(partDefinition.segmentExternalId, parsedCue.template, parsedCue.sources), + TallyTags.DVE_IS_LIVE + ] + }) - const userData = literal({ + const userData: ActionSelectDVE = { type: AdlibActionType.SELECT_DVE, config: parsedCue, videoId: partDefinition.fields.videoId, segmentExternalId: partDefinition.segmentExternalId + } + actions.push({ + externalId: generateExternalId(context, userData), + actionId: AdlibActionType.SELECT_DVE, + userData, + userDataManifest: {}, + display: { + _rank: rank, + sourceLayerId: OfftubeSourceLayer.PgmDVE, + outputLayerId: OfftubeOutputLayers.PGM, + label: t(`${partDefinition.storyName}`), + tags: [AdlibTags.ADLIB_KOMMENTATOR, ...(adlib ? [AdlibTags.ADLIB_FLOW_PRODUCER] : [])], + content: literal({ + ...pieceContent.content + }), + currentPieceTags: [GetTagForDVE(partDefinition.segmentExternalId, parsedCue.template, parsedCue.sources)], + nextPieceTags: [GetTagForDVENext(partDefinition.segmentExternalId, parsedCue.template, parsedCue.sources)] + } }) - actions.push( - literal({ - externalId: generateExternalId(context, userData), - actionId: AdlibActionType.SELECT_DVE, - userData, - userDataManifest: {}, - display: { - _rank: rank, - sourceLayerId: OfftubeSourceLayer.PgmDVE, - outputLayerId: OfftubeOutputLayers.PGM, - label: t(`${partDefinition.storyName}`), - tags: [AdlibTags.ADLIB_KOMMENTATOR, ...(adlib ? [AdlibTags.ADLIB_FLOW_PRODUCER] : [])], - content: literal({ - ...pieceContent.content - }), - currentPieceTags: [GetTagForDVE(partDefinition.segmentExternalId, parsedCue.template, parsedCue.sources)], - nextPieceTags: [GetTagForDVENext(partDefinition.segmentExternalId, parsedCue.template, parsedCue.sources)] - } - }) - ) } } diff --git a/src/tv2_offtube_showstyle/cues/OfftubeEkstern.ts b/src/tv2_offtube_showstyle/cues/OfftubeEkstern.ts index abcd29a45..1164e20a3 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeEkstern.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeEkstern.ts @@ -5,7 +5,7 @@ import { IBlueprintPiece, ISegmentUserContext } from '@tv2media/blueprints-integration' -import { CueDefinitionEkstern, EvaluateEksternBase, PartDefinition } from 'tv2-common' +import { CueDefinitionEkstern, EvaluateEksternBase, PartDefinition, PieceMetaData } from 'tv2-common' import { OfftubeAtemLLayer } from '../../tv2_offtube_studio/layers' import { OfftubeShowstyleBlueprintConfig } from '../helpers/config' import { OfftubeSourceLayer } from '../layers' @@ -14,8 +14,8 @@ export function OfftubeEvaluateEkstern( context: ISegmentUserContext, config: OfftubeShowstyleBlueprintConfig, part: IBlueprintPart, - pieces: IBlueprintPiece[], - _adlibPieces: IBlueprintAdLibPiece[], + pieces: Array>, + _adlibPieces: Array>, _actions: IBlueprintActionManifest[], partId: string, parsedCue: CueDefinitionEkstern, diff --git a/src/tv2_offtube_showstyle/cues/OfftubeGraphicBackgroundLoop.ts b/src/tv2_offtube_showstyle/cues/OfftubeGraphicBackgroundLoop.ts index 6acaf42de..2277c7248 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeGraphicBackgroundLoop.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeGraphicBackgroundLoop.ts @@ -27,66 +27,62 @@ export function OfftubeEvaluateCueBackgroundLoop( const path = `dve/${fileName}` const start = (parsedCue.start ? CalculateTime(parsedCue.start) : 0) ?? 0 if (adlib) { - adlibPieces.push( - literal({ - _rank: rank || 0, - externalId: partId, - name: fileName, - outputLayerId: SharedOutputLayers.SEC, - sourceLayerId: OfftubeSourceLayer.PgmDVEBackground, - lifespan: PieceLifespan.OutOnShowStyleEnd, - content: literal>({ - fileName, - path, - ignoreMediaObjectStatus: true, - timelineObjects: _.compact([ - literal({ - id: '', - enable: { start: 0 }, - priority: 100, - layer: OfftubeCasparLLayer.CasparCGDVELoop, - content: { - deviceType: TSR.DeviceType.CASPARCG, - type: TSR.TimelineContentTypeCasparCg.MEDIA, - file: path, - loop: true - } - }) - ]) - }) + adlibPieces.push({ + _rank: rank || 0, + externalId: partId, + name: fileName, + outputLayerId: SharedOutputLayers.SEC, + sourceLayerId: OfftubeSourceLayer.PgmDVEBackground, + lifespan: PieceLifespan.OutOnShowStyleEnd, + content: literal>({ + fileName, + path, + ignoreMediaObjectStatus: true, + timelineObjects: _.compact([ + literal({ + id: '', + enable: { start: 0 }, + priority: 100, + layer: OfftubeCasparLLayer.CasparCGDVELoop, + content: { + deviceType: TSR.DeviceType.CASPARCG, + type: TSR.TimelineContentTypeCasparCg.MEDIA, + file: path, + loop: true + } + }) + ]) }) - ) + }) } else { - pieces.push( - literal({ - externalId: partId, - name: fileName, - enable: { - start - }, - outputLayerId: SharedOutputLayers.SEC, - sourceLayerId: OfftubeSourceLayer.PgmDVEBackground, - lifespan: PieceLifespan.OutOnShowStyleEnd, - content: literal>({ - fileName, - path, - ignoreMediaObjectStatus: true, - timelineObjects: _.compact([ - literal({ - id: '', - enable: { start: 0 }, - priority: 100, - layer: OfftubeCasparLLayer.CasparCGDVELoop, - content: { - deviceType: TSR.DeviceType.CASPARCG, - type: TSR.TimelineContentTypeCasparCg.MEDIA, - file: path, - loop: true - } - }) - ]) - }) + pieces.push({ + externalId: partId, + name: fileName, + enable: { + start + }, + outputLayerId: SharedOutputLayers.SEC, + sourceLayerId: OfftubeSourceLayer.PgmDVEBackground, + lifespan: PieceLifespan.OutOnShowStyleEnd, + content: literal>({ + fileName, + path, + ignoreMediaObjectStatus: true, + timelineObjects: _.compact([ + literal({ + id: '', + enable: { start: 0 }, + priority: 100, + layer: OfftubeCasparLLayer.CasparCGDVELoop, + content: { + deviceType: TSR.DeviceType.CASPARCG, + type: TSR.TimelineContentTypeCasparCg.MEDIA, + file: path, + loop: true + } + }) + ]) }) - ) + }) } } diff --git a/src/tv2_offtube_showstyle/cues/OfftubeGraphics.ts b/src/tv2_offtube_showstyle/cues/OfftubeGraphics.ts index d24ae4d84..c09058e76 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeGraphics.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeGraphics.ts @@ -54,7 +54,7 @@ export function OfftubeEvaluateGrafikCaspar( segmentExternalId: partDefinition.segmentExternalId }) } else if (GraphicIsInternal(parsedCue)) { - CreateInternalGraphic(config, context, pieces, adlibPieces, actions, partId, parsedCue, partDefinition, adlib) + CreateInternalGraphic(config, context, pieces, adlibPieces, partId, parsedCue, partDefinition, adlib) } } diff --git a/src/tv2_offtube_showstyle/cues/OfftubeJingle.ts b/src/tv2_offtube_showstyle/cues/OfftubeJingle.ts index 8408b932a..f82cd7ba6 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeJingle.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeJingle.ts @@ -13,7 +13,6 @@ import { GetJinglePartProperties, GetTagForJingle, GetTagForJingleNext, - literal, PartDefinition, PieceMetaData, t, @@ -27,7 +26,7 @@ import { OfftubeOutputLayers, OfftubeSourceLayer } from '../layers' export function OfftubeEvaluateJingle( context: ISegmentUserContext, config: OfftubeShowstyleBlueprintConfig, - pieces: IBlueprintPiece[], + pieces: Array>, _adlibPieces: IBlueprintAdLibPiece[], actions: IBlueprintActionManifest[], parsedCue: CueDefinitionJingle, @@ -60,70 +59,66 @@ export function OfftubeEvaluateJingle( return } - const userData = literal({ + const userData: ActionSelectJingle = { type: AdlibActionType.SELECT_JINGLE, clip: parsedCue.clip, segmentExternalId: part.segmentExternalId + } + actions.push({ + externalId: generateExternalId(context, userData), + actionId: AdlibActionType.SELECT_JINGLE, + userData, + userDataManifest: {}, + display: { + label: t(effekt ? `EFFEKT ${parsedCue.clip}` : parsedCue.clip), + sourceLayerId: OfftubeSourceLayer.PgmJingle, + outputLayerId: OfftubeOutputLayers.JINGLE, + content: { + ...createJingleContentOfftube( + config, + file, + jingle.StartAlpha, + jingle.LoadFirstFrame, + jingle.Duration, + jingle.EndAlpha + ) + }, + tags: [AdlibTags.OFFTUBE_100pc_SERVER, AdlibTags.ADLIB_KOMMENTATOR], + currentPieceTags: [GetTagForJingle(part.segmentExternalId, parsedCue.clip)], + nextPieceTags: [GetTagForJingleNext(part.segmentExternalId, parsedCue.clip)] + } }) - actions.push( - literal({ - externalId: generateExternalId(context, userData), - actionId: AdlibActionType.SELECT_JINGLE, - userData, - userDataManifest: {}, - display: { - label: t(effekt ? `EFFEKT ${parsedCue.clip}` : parsedCue.clip), - sourceLayerId: OfftubeSourceLayer.PgmJingle, - outputLayerId: OfftubeOutputLayers.JINGLE, - content: { - ...createJingleContentOfftube( - config, - file, - jingle.StartAlpha, - jingle.LoadFirstFrame, - jingle.Duration, - jingle.EndAlpha - ) - }, - tags: [AdlibTags.OFFTUBE_100pc_SERVER, AdlibTags.ADLIB_KOMMENTATOR], - currentPieceTags: [GetTagForJingle(part.segmentExternalId, parsedCue.clip)], - nextPieceTags: [GetTagForJingleNext(part.segmentExternalId, parsedCue.clip)] - } - }) - ) - pieces.push( - literal({ - externalId: `${part.externalId}-JINGLE`, - name: effekt ? `EFFEKT ${parsedCue.clip}` : parsedCue.clip, - enable: { - start: 0 - }, - lifespan: PieceLifespan.WithinPart, - outputLayerId: SharedOutputLayers.JINGLE, - sourceLayerId: OfftubeSourceLayer.PgmJingle, - metaData: literal({ - sisyfosPersistMetaData: { - sisyfosLayers: [] - } - }), - prerollDuration: config.studio.CasparPrerollDuration + TimeFromFrames(Number(jingle.StartAlpha)), - content: createJingleContentOfftube( - config, - file, - jingle.StartAlpha, - jingle.LoadFirstFrame, - jingle.Duration, - jingle.EndAlpha - ), - tags: [ - GetTagForJingle(part.segmentExternalId, parsedCue.clip), - GetTagForJingleNext(part.segmentExternalId, parsedCue.clip), - TallyTags.JINGLE_IS_LIVE, - !effekt ? TallyTags.JINGLE : '' - ] - }) - ) + pieces.push({ + externalId: `${part.externalId}-JINGLE`, + name: effekt ? `EFFEKT ${parsedCue.clip}` : parsedCue.clip, + enable: { + start: 0 + }, + lifespan: PieceLifespan.WithinPart, + outputLayerId: SharedOutputLayers.JINGLE, + sourceLayerId: OfftubeSourceLayer.PgmJingle, + metaData: { + sisyfosPersistMetaData: { + sisyfosLayers: [] + } + }, + prerollDuration: config.studio.CasparPrerollDuration + TimeFromFrames(Number(jingle.StartAlpha)), + content: createJingleContentOfftube( + config, + file, + jingle.StartAlpha, + jingle.LoadFirstFrame, + jingle.Duration, + jingle.EndAlpha + ), + tags: [ + GetTagForJingle(part.segmentExternalId, parsedCue.clip), + GetTagForJingleNext(part.segmentExternalId, parsedCue.clip), + TallyTags.JINGLE_IS_LIVE, + !effekt ? TallyTags.JINGLE : '' + ] + }) } export function createJingleContentOfftube( diff --git a/src/tv2_offtube_showstyle/cues/OfftubePgmClean.ts b/src/tv2_offtube_showstyle/cues/OfftubePgmClean.ts index 124c9bd88..b54b086d4 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubePgmClean.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubePgmClean.ts @@ -34,33 +34,31 @@ export function OfftubeEvaluatePgmClean( return } - pieces.push( - literal({ - externalId: partId, - name, - enable: { - start: 0 - }, - outputLayerId: SharedOutputLayers.AUX, - sourceLayerId: OfftubeSourceLayer.AuxPgmClean, - lifespan: PieceLifespan.OutOnShowStyleEnd, - content: literal>({ - timelineObjects: literal([ - literal({ - id: '', - enable: { while: '1' }, - priority: 0, - layer: OfftubeAtemLLayer.AtemAuxClean, - content: { - deviceType: TSR.DeviceType.ATEM, - type: TSR.TimelineContentTypeAtem.AUX, - aux: { - input: sourceInfo.port - } + pieces.push({ + externalId: partId, + name, + enable: { + start: 0 + }, + outputLayerId: SharedOutputLayers.AUX, + sourceLayerId: OfftubeSourceLayer.AuxPgmClean, + lifespan: PieceLifespan.OutOnShowStyleEnd, + content: literal>({ + timelineObjects: literal([ + literal({ + id: '', + enable: { while: '1' }, + priority: 0, + layer: OfftubeAtemLLayer.AtemAuxClean, + content: { + deviceType: TSR.DeviceType.ATEM, + type: TSR.TimelineContentTypeAtem.AUX, + aux: { + input: sourceInfo.port } - }) - ]) - }) + } + }) + ]) }) - ) + }) } diff --git a/src/tv2_offtube_showstyle/getRundown.ts b/src/tv2_offtube_showstyle/getRundown.ts index 6ef998bdc..90ce6d901 100644 --- a/src/tv2_offtube_showstyle/getRundown.ts +++ b/src/tv2_offtube_showstyle/getRundown.ts @@ -259,55 +259,51 @@ function getGlobalAdlibActionsOfftube( function makeCutCameraActions(info: SourceInfo, queue: boolean, rank: number) { const sourceDefinition = SourceInfoToSourceDefinition(info) as SourceDefinitionKam - const userData = literal({ + const userData: ActionCutToCamera = { type: AdlibActionType.CUT_TO_CAMERA, queue, sourceDefinition + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.CUT_TO_CAMERA, + userData, + userDataManifest: {}, + display: { + _rank: rank, + label: t(sourceDefinition.name), + sourceLayerId: OfftubeSourceLayer.PgmCam, + outputLayerId: SharedOutputLayers.PGM, + content: {}, + tags: queue ? [AdlibTags.OFFTUBE_SET_CAM_NEXT, AdlibTags.ADLIB_QUEUE_NEXT] : [AdlibTags.ADLIB_CUT_DIRECT], + currentPieceTags: [GetTagForKam(sourceDefinition)], + nextPieceTags: [GetTagForKam(sourceDefinition)] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.CUT_TO_CAMERA, - userData, - userDataManifest: {}, - display: { - _rank: rank, - label: t(sourceDefinition.name), - sourceLayerId: OfftubeSourceLayer.PgmCam, - outputLayerId: SharedOutputLayers.PGM, - content: {}, - tags: queue ? [AdlibTags.OFFTUBE_SET_CAM_NEXT, AdlibTags.ADLIB_QUEUE_NEXT] : [AdlibTags.ADLIB_CUT_DIRECT], - currentPieceTags: [GetTagForKam(sourceDefinition)], - nextPieceTags: [GetTagForKam(sourceDefinition)] - } - }) - ) } function makeRemoteAction(sourceInfo: SourceInfo, rank: number) { const sourceDefinition = SourceInfoToSourceDefinition(sourceInfo) as SourceDefinitionRemote - const userData = literal({ + const userData: ActionCutToRemote = { type: AdlibActionType.CUT_TO_REMOTE, sourceDefinition + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.CUT_TO_REMOTE, + userData, + userDataManifest: {}, + display: { + _rank: rank, + label: t(`${sourceDefinition.name}`), + sourceLayerId: OfftubeSourceLayer.PgmLive, + outputLayerId: OfftubeOutputLayers.PGM, + content: {}, + tags: [AdlibTags.OFFTUBE_SET_REMOTE_NEXT, AdlibTags.ADLIB_QUEUE_NEXT], + currentPieceTags: [GetTagForLive(sourceDefinition)], + nextPieceTags: [GetTagForLive(sourceDefinition)] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.CUT_TO_REMOTE, - userData, - userDataManifest: {}, - display: { - _rank: rank, - label: t(`${sourceDefinition.name}`), - sourceLayerId: OfftubeSourceLayer.PgmLive, - outputLayerId: OfftubeOutputLayers.PGM, - content: {}, - tags: [AdlibTags.OFFTUBE_SET_REMOTE_NEXT, AdlibTags.ADLIB_QUEUE_NEXT], - currentPieceTags: [GetTagForLive(sourceDefinition)], - nextPieceTags: [GetTagForLive(sourceDefinition)] - } - }) - ) } function makeAdlibBoxesActions( @@ -318,63 +314,59 @@ function getGlobalAdlibActionsOfftube( for (let box = 0; box < NUMBER_OF_DVE_BOXES; box++) { const sourceDefinition = SourceInfoToSourceDefinition(info) const layer = type === SourceInfoType.KAM ? OfftubeSourceLayer.PgmCam : OfftubeSourceLayer.PgmLive - const userData = literal({ + const userData: ActionCutSourceToBox = { type: AdlibActionType.CUT_SOURCE_TO_BOX, name: sourceDefinition.name, box, sourceDefinition + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.CUT_SOURCE_TO_BOX, + userData, + userDataManifest: {}, + display: { + _rank: rank + 0.1 * box, + label: t(`${sourceDefinition.name} inp ${box + 1}`), + sourceLayerId: layer, + outputLayerId: OfftubeOutputLayers.PGM, + content: {}, + tags: [AdlibTagCutToBox(box)] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.CUT_SOURCE_TO_BOX, - userData, - userDataManifest: {}, - display: { - _rank: rank + 0.1 * box, - label: t(`${sourceDefinition.name} inp ${box + 1}`), - sourceLayerId: layer, - outputLayerId: OfftubeOutputLayers.PGM, - content: {}, - tags: [AdlibTagCutToBox(box)] - } - }) - ) } } function makeServerAdlibBoxesActions(rank: number) { for (let box = 0; box < NUMBER_OF_DVE_BOXES; box++) { - const userData = literal({ + const userData: ActionCutSourceToBox = { type: AdlibActionType.CUT_SOURCE_TO_BOX, name: `SERVER`, box, sourceDefinition: { sourceType: SourceType.SERVER } + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.CUT_SOURCE_TO_BOX, + userData, + userDataManifest: {}, + display: { + _rank: rank + 0.1 * box, + label: t(`Server inp ${box + 1}`), + sourceLayerId: OfftubeSourceLayer.PgmServer, + outputLayerId: SharedOutputLayers.SEC, + content: {}, + tags: [AdlibTagCutToBox(box)] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.CUT_SOURCE_TO_BOX, - userData, - userDataManifest: {}, - display: { - _rank: rank + 0.1 * box, - label: t(`Server inp ${box + 1}`), - sourceLayerId: OfftubeSourceLayer.PgmServer, - outputLayerId: SharedOutputLayers.SEC, - content: {}, - tags: [AdlibTagCutToBox(box)] - } - }) - ) } } - function makeCommentatorSelectServerAction() { - const userData = literal({ + function makeCommentatorSelectServerAction(): IBlueprintActionManifest { + const userData: ActionCommentatorSelectServer = { type: AdlibActionType.COMMENTATOR_SELECT_SERVER - }) - return literal({ + } + return { externalId: generateExternalId(_context, userData), actionId: AdlibActionType.COMMENTATOR_SELECT_SERVER, userData, @@ -389,16 +381,16 @@ function getGlobalAdlibActionsOfftube( currentPieceTags: [TallyTags.SERVER_IS_LIVE], nextPieceTags: [TallyTags.SERVER_IS_LIVE] } - }) + } } blueprintActions.push(makeCommentatorSelectServerAction()) - function makeCommentatorSelectDveAction() { - const userData = literal({ + function makeCommentatorSelectDveAction(): IBlueprintActionManifest { + const userData: ActionCommentatorSelectDVE = { type: AdlibActionType.COMMENTATOR_SELECT_DVE - }) - return literal({ + } + return { externalId: generateExternalId(_context, userData), actionId: AdlibActionType.COMMENTATOR_SELECT_DVE, userData, @@ -413,16 +405,16 @@ function getGlobalAdlibActionsOfftube( currentPieceTags: [TallyTags.DVE_IS_LIVE], nextPieceTags: [TallyTags.DVE_IS_LIVE] } - }) + } } blueprintActions.push(makeCommentatorSelectDveAction()) - function makeCommentatorSelectFullAction() { - const userData = literal({ + function makeCommentatorSelectFullAction(): IBlueprintActionManifest { + const userData: ActionCommentatorSelectFull = { type: AdlibActionType.COMMENTATOR_SELECT_FULL - }) - return literal({ + } + return { externalId: generateExternalId(_context, userData), actionId: AdlibActionType.COMMENTATOR_SELECT_FULL, userData, @@ -437,18 +429,18 @@ function getGlobalAdlibActionsOfftube( currentPieceTags: [TallyTags.FULL_IS_LIVE], nextPieceTags: [TallyTags.FULL_IS_LIVE] } - }) + } } blueprintActions.push(makeCommentatorSelectFullAction()) - function makeClearGraphicsAltudAction() { - const userData = literal({ + function makeClearGraphicsAltudAction(): IBlueprintActionManifest { + const userData: ActionClearGraphics = { type: AdlibActionType.CLEAR_GRAPHICS, sendCommands: false, label: 'GFX Altud' - }) - return literal({ + } + return { externalId: generateExternalId(_context, userData), actionId: AdlibActionType.CLEAR_GRAPHICS, userData, @@ -463,18 +455,18 @@ function getGlobalAdlibActionsOfftube( currentPieceTags: [TallyTags.GFX_ALTUD], nextPieceTags: [TallyTags.GFX_ALTUD] } - }) + } } blueprintActions.push(makeClearGraphicsAltudAction()) blueprintActions.push(...GetTransitionAdLibActions(config, 800)) - function makeRecallLastDveAction() { - const userData = literal({ + function makeRecallLastDveAction(): IBlueprintActionManifest { + const userData: ActionRecallLastDVE = { type: AdlibActionType.RECALL_LAST_DVE - }) - return literal({ + } + return { externalId: generateExternalId(_context, userData), actionId: AdlibActionType.RECALL_LAST_DVE, userData, @@ -486,31 +478,29 @@ function getGlobalAdlibActionsOfftube( outputLayerId: 'pgm', tags: [AdlibTags.ADLIB_RECALL_LAST_DVE] } - }) + } } blueprintActions.push(makeRecallLastDveAction()) _.each(config.showStyle.DVEStyles, (dveConfig, i) => { - const userData = literal({ + const userData: ActionSelectDVELayout = { type: AdlibActionType.SELECT_DVE_LAYOUT, config: dveConfig + } + blueprintActions.push({ + externalId: generateExternalId(_context, userData), + actionId: AdlibActionType.SELECT_DVE_LAYOUT, + userData, + userDataManifest: {}, + display: { + _rank: 200 + i, + label: t(dveConfig.DVEName), + sourceLayerId: OfftubeSourceLayer.PgmDVEAdLib, + outputLayerId: SharedOutputLayers.PGM, + tags: [AdlibTags.ADLIB_SELECT_DVE_LAYOUT, dveConfig.DVEName] + } }) - blueprintActions.push( - literal({ - externalId: generateExternalId(_context, userData), - actionId: AdlibActionType.SELECT_DVE_LAYOUT, - userData, - userDataManifest: {}, - display: { - _rank: 200 + i, - label: t(dveConfig.DVEName), - sourceLayerId: OfftubeSourceLayer.PgmDVEAdLib, - outputLayerId: SharedOutputLayers.PGM, - tags: [AdlibTags.ADLIB_SELECT_DVE_LAYOUT, dveConfig.DVEName] - } - }) - ) }) config.sources.cameras @@ -531,11 +521,11 @@ function getGlobalAdlibActionsOfftube( makeAdlibBoxesActions(o, SourceInfoType.KAM, globalRank++) }) - function makeRecallLastLiveAction() { - const userData = literal({ + function makeRecallLastLiveAction(): IBlueprintActionManifest { + const userData: ActionRecallLastLive = { type: AdlibActionType.RECALL_LAST_LIVE - }) - return literal({ + } + return { externalId: generateExternalId(_context, userData), actionId: AdlibActionType.RECALL_LAST_LIVE, userData, @@ -547,7 +537,7 @@ function getGlobalAdlibActionsOfftube( outputLayerId: SharedOutputLayers.PGM, tags: [AdlibTags.ADLIB_RECALL_LAST_LIVE] } - }) + } } blueprintActions.push(makeRecallLastLiveAction()) @@ -578,11 +568,11 @@ function getGlobalAdlibActionsOfftube( makeServerAdlibBoxesActions(globalRank++) - function makeCommentatorSelectJingleAction() { - const userData = literal({ + function makeCommentatorSelectJingleAction(): IBlueprintActionManifest { + const userData: ActionCommentatorSelectJingle = { type: AdlibActionType.COMMENTATOR_SELECT_JINGLE - }) - return literal({ + } + return { externalId: generateExternalId(_context, userData), actionId: AdlibActionType.COMMENTATOR_SELECT_JINGLE, userData, @@ -597,7 +587,7 @@ function getGlobalAdlibActionsOfftube( currentPieceTags: [TallyTags.JINGLE_IS_LIVE], nextPieceTags: [TallyTags.JINGLE_IS_LIVE] } - }) + } } blueprintActions.push(makeCommentatorSelectJingleAction()) diff --git a/src/tv2_offtube_showstyle/getSegment.ts b/src/tv2_offtube_showstyle/getSegment.ts index 5c0175639..eedba6e0c 100644 --- a/src/tv2_offtube_showstyle/getSegment.ts +++ b/src/tv2_offtube_showstyle/getSegment.ts @@ -2,7 +2,6 @@ import { BlueprintResultPart, BlueprintResultSegment, CameraContent, - IBlueprintPiece, IngestSegment, ISegmentUserContext, PieceLifespan, @@ -53,15 +52,18 @@ export async function getSegment( } } -function CreatePartContinuity(config: OfftubeShowstyleBlueprintConfig, ingestSegment: IngestSegment) { - return literal({ +function CreatePartContinuity( + config: OfftubeShowstyleBlueprintConfig, + ingestSegment: IngestSegment +): BlueprintResultPart { + return { part: { externalId: `${ingestSegment.externalId}-CONTINUITY`, title: 'CONTINUITY', untimed: true }, pieces: [ - literal({ + { externalId: `${ingestSegment.externalId}-CONTINUITY`, enable: { start: 0 @@ -92,9 +94,9 @@ function CreatePartContinuity(config: OfftubeShowstyleBlueprintConfig, ingestSeg }) ]) }) - }) + } ], adLibPieces: [], actions: [] - }) + } } diff --git a/src/tv2_offtube_showstyle/migrations/hotkeys.ts b/src/tv2_offtube_showstyle/migrations/hotkeys.ts index 472ec9650..52a07d7fe 100644 --- a/src/tv2_offtube_showstyle/migrations/hotkeys.ts +++ b/src/tv2_offtube_showstyle/migrations/hotkeys.ts @@ -24,7 +24,7 @@ export function GetDefaultStudioSourcesForOfftube(context: MigrationContextShowS const camera = manifestOfftubeSourcesCam.defaultVal.map(source => source.SourceName) as string[] const remote = manifestOfftubeSourcesRM.defaultVal.map(source => source.SourceName) as string[] - const feed = manifestOfftubeSourcesFeed.defaultVal.map(source => `F${source.SourceName}`) as string[] + const feed = manifestOfftubeSourcesFeed.defaultVal.map(source => `F${source.SourceName}`) const local: string[] = [] return { diff --git a/src/tv2_offtube_showstyle/migrations/index.ts b/src/tv2_offtube_showstyle/migrations/index.ts index 708fa1412..9ca3d320d 100644 --- a/src/tv2_offtube_showstyle/migrations/index.ts +++ b/src/tv2_offtube_showstyle/migrations/index.ts @@ -4,7 +4,6 @@ import { changeGFXTemplate, GetDefaultAdLibTriggers, GetDSKSourceLayerNames, - literal, RemoveOldShortcuts, removeSourceLayer, renameSourceLayer, @@ -16,7 +15,6 @@ import { UpsertValuesIntoTransitionTable } from 'tv2-common' import { SharedGraphicLLayer, SharedSourceLayers } from 'tv2-constants' -import * as _ from 'underscore' import { ATEMModel } from '../../types/atem' import { OfftubeSourceLayer } from '../layers' import { GetDefaultStudioSourcesForOfftube } from './hotkeys' @@ -71,7 +69,7 @@ const SHOW_STYLE_ID = 'tv2_offtube_showstyle' * 0.1.0: Core 0.24.0 */ -export const showStyleMigrations: MigrationStepShowStyle[] = literal([ +export const showStyleMigrations: MigrationStepShowStyle[] = [ // Fill in any layers that did not exist before // Note: These should only be run as the very final step of all migrations. otherwise they will add items too early, and confuse old migrations ...getCreateVariantMigrationSteps(), @@ -155,7 +153,7 @@ export const showStyleMigrations: MigrationStepShowStyle[] = literal { - return literal({ + return { id: `${versionStr}.sourcelayer.defaults${force ? '.forced' : ''}.${defaultVal._id}`, version: versionStr, canBeRunAutomatically: true, @@ -39,13 +39,13 @@ export function getSourceLayerDefaultsMigrationSteps(versionStr: string, force?: context.insertSourceLayer(defaultVal._id, defaultVal) } } - }) + } }) ) } export function forceSettingToDefaults(versionStr: string, setting: string): MigrationStepShowStyle { - return literal({ + return { id: `${versionStr}.sourcelayer.defaults.${setting}.forced`, version: versionStr, canBeRunAutomatically: true, @@ -78,13 +78,13 @@ export function forceSettingToDefaults(versionStr: string, setting: string): Mig context.setBaseConfig(setting, defaultVal.defaultVal) } } - }) + } } export function getOutputLayerDefaultsMigrationSteps(versionStr: string): MigrationStepShowStyle[] { return _.compact( _.map(OutputlayerDefaults, (defaultVal: IOutputLayer): MigrationStepShowStyle | null => { - return literal({ + return { id: `${versionStr}.outputlayer.defaults.${defaultVal._id}`, version: versionStr, canBeRunAutomatically: true, @@ -99,7 +99,7 @@ export function getOutputLayerDefaultsMigrationSteps(versionStr: string): Migrat context.insertOutputLayer(defaultVal._id, defaultVal) } } - }) + } }) ) } @@ -112,7 +112,7 @@ function remapTableColumnValuesInner( ): { changed: number; table: TableConfigItemValue } { let changed = 0 - table.map(row => { + table.forEach(row => { const val = row[columnId] if (val) { @@ -123,8 +123,6 @@ function remapTableColumnValuesInner( changed++ } } - - return row }) return { changed, table } diff --git a/src/tv2_offtube_showstyle/onTimelineGenerate.ts b/src/tv2_offtube_showstyle/onTimelineGenerate.ts index a173c4355..805cbe46f 100644 --- a/src/tv2_offtube_showstyle/onTimelineGenerate.ts +++ b/src/tv2_offtube_showstyle/onTimelineGenerate.ts @@ -7,7 +7,13 @@ import { TimelinePersistentState, TSR } from '@tv2media/blueprints-integration' -import { disablePilotWipeAfterJingle, onTimelineGenerate, PartEndStateExt, TimelineBlueprintExt } from 'tv2-common' +import { + disablePilotWipeAfterJingle, + onTimelineGenerate, + PartEndStateExt, + PieceMetaData, + TimelineBlueprintExt +} from 'tv2-common' import { SharedGraphicLLayer, TallyTags } from 'tv2-constants' import { OfftubeAtemLLayer, OfftubeCasparLLayer, OfftubeSisyfosLLayer } from '../tv2_offtube_studio/layers' import { getConfig } from './helpers/config' @@ -17,7 +23,7 @@ export function onTimelineGenerateOfftube( timeline: OnGenerateTimelineObj[], previousPersistentState: TimelinePersistentState | undefined, previousPartEndState: PartEndState | undefined, - resolvedPieces: IBlueprintResolvedPieceInstance[] + resolvedPieces: Array> ): Promise { const previousPartEndState2 = previousPartEndState as PartEndStateExt | undefined disablePilotWipeAfterJingle(timeline, previousPartEndState2, resolvedPieces) diff --git a/src/tv2_offtube_showstyle/parts/OfftubeDVE.ts b/src/tv2_offtube_showstyle/parts/OfftubeDVE.ts index f8cfbc835..e4c365924 100644 --- a/src/tv2_offtube_showstyle/parts/OfftubeDVE.ts +++ b/src/tv2_offtube_showstyle/parts/OfftubeDVE.ts @@ -7,7 +7,7 @@ import { IBlueprintPiece, ISegmentUserContext } from '@tv2media/blueprints-integration' -import { AddScript, literal, PartDefinitionDVE, PartTime } from 'tv2-common' +import { AddScript, PartDefinitionDVE, PartTime } from 'tv2-common' import { OfftubeShowstyleBlueprintConfig } from '../helpers/config' import { OfftubeEvaluateCues } from '../helpers/EvaluateCues' import { OfftubeSourceLayer } from '../layers' @@ -20,12 +20,12 @@ export async function OfftubeCreatePartDVE( ): Promise { const partTime = PartTime(config, partDefinition, totalWords, false) - const part = literal({ + const part: IBlueprintPart = { externalId: partDefinition.externalId, title: partDefinition.title || `DVE`, autoNext: false, expectedDuration: partTime - }) + } const pieces: IBlueprintPiece[] = [] const adLibPieces: IBlueprintAdLibPiece[] = [] const actions: IBlueprintActionManifest[] = [] diff --git a/src/tv2_offtube_showstyle/parts/OfftubeGrafik.ts b/src/tv2_offtube_showstyle/parts/OfftubeGrafik.ts index 8282b8deb..e04113b16 100644 --- a/src/tv2_offtube_showstyle/parts/OfftubeGrafik.ts +++ b/src/tv2_offtube_showstyle/parts/OfftubeGrafik.ts @@ -6,7 +6,7 @@ import { IBlueprintPiece, ISegmentUserContext } from '@tv2media/blueprints-integration' -import { AddScript, ApplyFullGraphicPropertiesToPart, literal, PartDefinition, PartTime } from 'tv2-common' +import { AddScript, ApplyFullGraphicPropertiesToPart, PartDefinition, PartTime } from 'tv2-common' import { OfftubeShowstyleBlueprintConfig } from '../helpers/config' import { OfftubeEvaluateCues } from '../helpers/EvaluateCues' import { OfftubeSourceLayer } from '../layers' @@ -20,13 +20,13 @@ export async function OfftubeCreatePartGrafik( ) { const partTime = PartTime(config, partDefinition, totalWords) - const part = literal({ + const part: IBlueprintPart = { externalId: partDefinition.externalId, title: partDefinition.title || partDefinition.type + ' - ' + partDefinition.rawType, metaData: {}, autoNext: false, expectedDuration: partTime - }) + } const adLibPieces: IBlueprintAdLibPiece[] = [] const pieces: IBlueprintPiece[] = [] diff --git a/src/tv2_offtube_showstyle/parts/OfftubeKam.ts b/src/tv2_offtube_showstyle/parts/OfftubeKam.ts index e1cc27c68..055679741 100644 --- a/src/tv2_offtube_showstyle/parts/OfftubeKam.ts +++ b/src/tv2_offtube_showstyle/parts/OfftubeKam.ts @@ -23,7 +23,7 @@ import { GetTagForKam, literal, PartDefinitionKam, - SisyfosPersistMetaData, + PieceMetaData, TransitionSettings } from 'tv2-common' import { SharedOutputLayers, TallyTags } from 'tv2-constants' @@ -45,48 +45,46 @@ export async function OfftubeCreatePartKam( const partTime = partKamBase.duration const adLibPieces: IBlueprintAdLibPiece[] = [] - const pieces: IBlueprintPiece[] = [] + const pieces: Array> = [] const actions: IBlueprintActionManifest[] = [] const mediaSubscriptions: HackPartMediaObjectSubscription[] = [] const jingleDSK = FindDSKJingle(config) if (/cs ?3/i.test(partDefinition.sourceDefinition.id)) { - pieces.push( - literal({ - externalId: partDefinition.externalId, - name: 'CS 3 (JINGLE)', - enable: { start: 0 }, - outputLayerId: SharedOutputLayers.PGM, - sourceLayerId: OfftubeSourceLayer.PgmJingle, - lifespan: PieceLifespan.WithinPart, - tags: [GetTagForKam(partDefinition.sourceDefinition), TallyTags.JINGLE_IS_LIVE], - content: literal>({ - ignoreMediaObjectStatus: true, - fileName: '', - path: '', - timelineObjects: literal([ - literal({ - id: ``, - enable: { - start: 0 - }, - priority: 1, - layer: OfftubeAtemLLayer.AtemMEClean, - content: { - deviceType: TSR.DeviceType.ATEM, - type: TSR.TimelineContentTypeAtem.ME, - me: { - input: jingleDSK.Fill, - transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, - transitionSettings: TransitionSettings(config, partDefinition) - } + pieces.push({ + externalId: partDefinition.externalId, + name: 'CS 3 (JINGLE)', + enable: { start: 0 }, + outputLayerId: SharedOutputLayers.PGM, + sourceLayerId: OfftubeSourceLayer.PgmJingle, + lifespan: PieceLifespan.WithinPart, + tags: [GetTagForKam(partDefinition.sourceDefinition), TallyTags.JINGLE_IS_LIVE], + content: literal>({ + ignoreMediaObjectStatus: true, + fileName: '', + path: '', + timelineObjects: literal([ + literal({ + id: ``, + enable: { + start: 0 + }, + priority: 1, + layer: OfftubeAtemLLayer.AtemMEClean, + content: { + deviceType: TSR.DeviceType.ATEM, + type: TSR.TimelineContentTypeAtem.ME, + me: { + input: jingleDSK.Fill, + transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, + transitionSettings: TransitionSettings(config, partDefinition) } - }) - ]) - }) + } + }) + ]) }) - ) + }) } else { const sourceInfoCam = findSourceInfo(config.sources, partDefinition.sourceDefinition) if (sourceInfoCam === undefined) { @@ -96,51 +94,49 @@ export async function OfftubeCreatePartKam( part = { ...part, ...CreateEffektForpart(context, config, partDefinition, pieces) } - pieces.push( - literal({ - externalId: partDefinition.externalId, - name: part.title, - enable: { start: 0 }, - outputLayerId: SharedOutputLayers.PGM, - sourceLayerId: OfftubeSourceLayer.PgmCam, - lifespan: PieceLifespan.WithinPart, - metaData: { - sisyfosPersistMetaData: literal({ - sisyfosLayers: sourceInfoCam.sisyfosLayers ?? [], - acceptPersistAudio: sourceInfoCam.acceptPersistAudio - }) - }, - tags: [GetTagForKam(partDefinition.sourceDefinition)], - content: { - studioLabel: '', - switcherInput: atemInput, - timelineObjects: literal([ - literal({ - id: ``, - enable: { - start: 0 - }, - priority: 1, - layer: OfftubeAtemLLayer.AtemMEClean, - content: { - deviceType: TSR.DeviceType.ATEM, - type: TSR.TimelineContentTypeAtem.ME, - me: { - input: Number(atemInput), - transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, - transitionSettings: TransitionSettings(config, partDefinition) - } - }, - ...(AddParentClass(config, partDefinition) - ? { classes: [CameraParentClass('studio0', partDefinition.sourceDefinition.id)] } - : {}) - }), - - ...GetSisyfosTimelineObjForCamera(config, sourceInfoCam, partDefinition.sourceDefinition.minusMic) - ]) + pieces.push({ + externalId: partDefinition.externalId, + name: part.title, + enable: { start: 0 }, + outputLayerId: SharedOutputLayers.PGM, + sourceLayerId: OfftubeSourceLayer.PgmCam, + lifespan: PieceLifespan.WithinPart, + metaData: { + sisyfosPersistMetaData: { + sisyfosLayers: sourceInfoCam.sisyfosLayers ?? [], + acceptPersistAudio: sourceInfoCam.acceptPersistAudio } - }) - ) + }, + tags: [GetTagForKam(partDefinition.sourceDefinition)], + content: { + studioLabel: '', + switcherInput: atemInput, + timelineObjects: literal([ + literal({ + id: ``, + enable: { + start: 0 + }, + priority: 1, + layer: OfftubeAtemLLayer.AtemMEClean, + content: { + deviceType: TSR.DeviceType.ATEM, + type: TSR.TimelineContentTypeAtem.ME, + me: { + input: Number(atemInput), + transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, + transitionSettings: TransitionSettings(config, partDefinition) + } + }, + ...(AddParentClass(config, partDefinition) + ? { classes: [CameraParentClass('studio0', partDefinition.sourceDefinition.id)] } + : {}) + }), + + ...GetSisyfosTimelineObjForCamera(config, sourceInfoCam, partDefinition.sourceDefinition.minusMic) + ]) + } + }) } await OfftubeEvaluateCues( diff --git a/src/tv2_offtube_showstyle/parts/OfftubeUnknown.ts b/src/tv2_offtube_showstyle/parts/OfftubeUnknown.ts index 0b90e1fa3..ececf2cbf 100644 --- a/src/tv2_offtube_showstyle/parts/OfftubeUnknown.ts +++ b/src/tv2_offtube_showstyle/parts/OfftubeUnknown.ts @@ -11,7 +11,6 @@ import { ApplyFullGraphicPropertiesToPart, GetJinglePartProperties, GraphicIsPilot, - literal, PartDefinition, PartTime } from 'tv2-common' @@ -29,13 +28,13 @@ export async function CreatePartUnknown( ) { const partTime = PartTime(config, partDefinition, totalWords) - let part = literal({ + let part: IBlueprintPart = { externalId: partDefinition.externalId, title: partDefinition.title || partDefinition.type + ' - ' + partDefinition.rawType, metaData: {}, autoNext: false, expectedDuration: partTime - }) + } const adLibPieces: IBlueprintAdLibPiece[] = [] const pieces: IBlueprintPiece[] = [] diff --git a/src/tv2_offtube_showstyle/postProcessTimelineObjects.ts b/src/tv2_offtube_showstyle/postProcessTimelineObjects.ts index fe1b658cb..44e44292f 100644 --- a/src/tv2_offtube_showstyle/postProcessTimelineObjects.ts +++ b/src/tv2_offtube_showstyle/postProcessTimelineObjects.ts @@ -7,7 +7,7 @@ import { TimelineObjHoldMode, TSR } from '@tv2media/blueprints-integration' -import { literal, TimelineBlueprintExt, TV2BlueprintConfig } from 'tv2-common' +import { TimelineBlueprintExt, TV2BlueprintConfig } from 'tv2-common' import { ControlClasses } from 'tv2-constants' import _ = require('underscore') import { OfftubeAbstractLLayer, OfftubeAtemLLayer } from '../tv2_offtube_studio/layers' @@ -60,7 +60,7 @@ export function postProcessPieceTimelineObjects( ) { if (tlObj.classes?.includes(ControlClasses.AbstractLookahead)) { // Create a lookahead-lookahead object for this me-program - const lookaheadObj = literal({ + const lookaheadObj: TSR.TimelineObjAbstractAny & TimelineBlueprintExt = { id: '', enable: { start: 0 }, priority: tlObj.holdMode === TimelineObjHoldMode.ONLY ? 5 : 0, // Must be below lookahead, except when forced by hold @@ -74,11 +74,11 @@ export function postProcessPieceTimelineObjects( mediaPlayerSession: tlObj.metaData?.mediaPlayerSession }, classes: ['ab_on_preview'] - }) + } extraObjs.push(lookaheadObj) } else { // Create a lookahead-lookahead object for this me-program - const lookaheadObj = literal({ + const lookaheadObj: TSR.TimelineObjAtemME & TimelineBlueprintExt = { id: '', enable: { start: 0 }, priority: tlObj.holdMode === TimelineObjHoldMode.ONLY ? 5 : 0, // Must be below lookahead, except when forced by hold @@ -97,7 +97,7 @@ export function postProcessPieceTimelineObjects( mediaPlayerSession: tlObj.metaData?.mediaPlayerSession }, classes: ['ab_on_preview'] - }) + } extraObjs.push(lookaheadObj) } } diff --git a/src/tv2_offtube_studio/getBaseline.ts b/src/tv2_offtube_studio/getBaseline.ts index d20332296..7e3ce879d 100644 --- a/src/tv2_offtube_studio/getBaseline.ts +++ b/src/tv2_offtube_studio/getBaseline.ts @@ -10,7 +10,7 @@ import * as _ from 'underscore' import { AtemSourceIndex } from '../types/atem' import { OfftubeStudioBlueprintConfig } from './helpers/config' import { OfftubeAtemLLayer, OfftubeSisyfosLLayer } from './layers' -import { SisyfosChannel, sisyfosChannels } from './sisyfosChannels' +import { sisyfosChannels } from './sisyfosChannels' function filterMappings( input: BlueprintMappings, @@ -30,14 +30,14 @@ function filterMappings( export function getBaseline(context: IStudioContext): BlueprintResultBaseline { const mappings = context.getStudioMappings() - const config = (context.getStudioConfig() as unknown) as OfftubeStudioBlueprintConfig + const config = context.getStudioConfig() as OfftubeStudioBlueprintConfig const sisyfosMappings = filterMappings(mappings, (_id, v) => v.device === TSR.DeviceType.SISYFOS) const mappedChannels: TSR.TimelineObjSisyfosChannels['content']['channels'] = [] for (const id in sisyfosMappings) { if (sisyfosMappings[id]) { - const sisyfosChannel = sisyfosChannels[id as OfftubeSisyfosLLayer] as SisyfosChannel | undefined + const sisyfosChannel = sisyfosChannels[id as OfftubeSisyfosLLayer] if (sisyfosChannel) { mappedChannels.push({ mappedLayer: id, diff --git a/src/tv2_offtube_studio/migrations/devices.ts b/src/tv2_offtube_studio/migrations/devices.ts index d088ad397..ae375657d 100644 --- a/src/tv2_offtube_studio/migrations/devices.ts +++ b/src/tv2_offtube_studio/migrations/devices.ts @@ -5,7 +5,6 @@ import { MigrationStepStudio, TSR } from '@tv2media/blueprints-integration' -import { literal } from 'tv2-common' import * as _ from 'underscore' declare const VERSION: string // Injected by webpack @@ -218,10 +217,10 @@ const devices: DeviceEntry[] = [ } ] -export const deviceMigrations = literal([ +export const deviceMigrations: MigrationStepStudio[] = [ // create all devices ..._.map(devices, createDevice), // ensure all devices still look valid ..._.map(devices, validateDevice) -]) +] diff --git a/src/tv2_offtube_studio/migrations/index.ts b/src/tv2_offtube_studio/migrations/index.ts index 9c58d89e4..9c55ff58f 100644 --- a/src/tv2_offtube_studio/migrations/index.ts +++ b/src/tv2_offtube_studio/migrations/index.ts @@ -6,7 +6,6 @@ import { } from '@tv2media/blueprints-integration' import { AddKeepAudio, - literal, MoveClipSourcePath, MoveSourcesToTable, RemoveConfig, @@ -41,7 +40,7 @@ function renameAudioSources(versionStr: string, renaming: Map): const steps: MigrationStepStudio[] = [] for (const layer in renaming) { if (layer in renaming) { - const res = literal({ + const res: MigrationStepStudio = { id: `${versionStr}.studioConfig.renameAudioSources.${layer}`, version: versionStr, canBeRunAutomatically: true, @@ -64,7 +63,7 @@ function renameAudioSources(versionStr: string, renaming: Map): } } } - }) + } steps.push(res) } @@ -74,7 +73,7 @@ function renameAudioSources(versionStr: string, renaming: Map): } function ensureMappingDeleted(versionStr: string, mapping: string): MigrationStepStudio { - const res = literal({ + return { id: `${versionStr}.studioConfig.ensureMappingDeleted.${mapping}`, version: versionStr, canBeRunAutomatically: true, @@ -92,9 +91,7 @@ function ensureMappingDeleted(versionStr: string, mapping: string): MigrationSte context.removeMapping(mapping) } } - }) - - return res + } } function remapTableColumnValuesInner( @@ -105,7 +102,7 @@ function remapTableColumnValuesInner( ): { changed: number; table: TableConfigItemValue } { let changed = 0 - table.map(row => { + table.forEach(row => { const val = row[columnId] if (val) { @@ -127,8 +124,6 @@ function remapTableColumnValuesInner( } } } - - return row }) return { changed, table } @@ -142,7 +137,7 @@ function remapTableColumnValues( remapping: Map ): MigrationStepStudio[] { return [ - literal({ + { id: `${versionStr}.remapTableColumnValue.${tableId}.${columnId}`, version: versionStr, canBeRunAutomatically: true, @@ -179,7 +174,7 @@ function remapTableColumnValues( context.setConfig(tableId, ret.table) } - }) + } ] } @@ -190,7 +185,7 @@ const audioSourceRenaming: Map = new Map([ ['sisyfos_source_world_feed_surround', OfftubeSisyfosLLayer.SisyfosSourceLive_3] ]) -export const studioMigrations: MigrationStepStudio[] = literal([ +export const studioMigrations: MigrationStepStudio[] = [ ensureStudioConfig( '0.1.0', 'SourcesCam', @@ -370,4 +365,4 @@ export const studioMigrations: MigrationStepStudio[] = literal { - return literal({ + return { id: `${versionStr}.mappings.defaults.${id}`, version: versionStr, canBeRunAutomatically: true, @@ -150,11 +149,9 @@ export function getMappingsDefaultsMigrationSteps(versionStr: string): Migration context.insertMapping(id, defaultVal) } } - }) + } }) ) - - return res } export function GetMappingDefaultMigrationStepForLayer( @@ -162,7 +159,7 @@ export function GetMappingDefaultMigrationStepForLayer( layer: string, force?: boolean ): MigrationStepStudio { - return literal({ + return { id: `${versionStr}.mappings.defaults.manualEnsure${layer}`, version: versionStr, canBeRunAutomatically: true, @@ -189,7 +186,7 @@ export function GetMappingDefaultMigrationStepForLayer( context.insertMapping(layer, MappingsDefaults[layer]) } } - }) + } } export function GetSisyfosLayersForTableMigrationOfftube(configName: string, val: string): string[] { diff --git a/src/tv2_system/migrations/hotkeys.ts b/src/tv2_system/migrations/hotkeys.ts index ae6f98a45..7f0ce7b08 100644 --- a/src/tv2_system/migrations/hotkeys.ts +++ b/src/tv2_system/migrations/hotkeys.ts @@ -6,12 +6,11 @@ import { PlayoutActions, TriggerType } from '@tv2media/blueprints-integration' -import { literal } from 'tv2-common' -export function RemoveDefaultCoreShortcuts(versionStr: string) { +export function RemoveDefaultCoreShortcuts(versionStr: string): MigrationStepSystem { const defaultTriggerIds = DEFAULT_CORE_TRIGGERS.map(trigger => trigger._id) - return literal({ + return { id: `${versionStr}.disableCoreDefaultTriggers`, version: versionStr, canBeRunAutomatically: true, @@ -34,7 +33,7 @@ export function RemoveDefaultCoreShortcuts(versionStr: string) { } } } - }) + } } // copy-pasted from core migrations diff --git a/src/tv2_system/migrations/index.ts b/src/tv2_system/migrations/index.ts index a79e12524..5d86532c1 100644 --- a/src/tv2_system/migrations/index.ts +++ b/src/tv2_system/migrations/index.ts @@ -1,9 +1,6 @@ import { MigrationStepSystem } from '@tv2media/blueprints-integration' -import { literal } from 'tv2-common' import { RemoveDefaultCoreShortcuts } from './hotkeys' declare const VERSION: string // Injected by webpack -export const systemMigrations: MigrationStepSystem[] = literal([ - RemoveDefaultCoreShortcuts(VERSION) -]) +export const systemMigrations: MigrationStepSystem[] = [RemoveDefaultCoreShortcuts(VERSION)]