diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index c7d71434b..761093923 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -1,23 +1,71 @@ -name: automerge +name: Scheduled Automerge Master -> Staging -> Develop on: schedule: - - cron: '15 0 * * *' # every night + - cron: '0 0 * * 1-5' # At 00:00, Monday through Friday workflow_dispatch: # on button click jobs: - merge-staging-to-dev: + merge-master-to-staging: + name: Merge Master to Staging runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set Git config run: | - git config --local user.email "${GITHUB_ACTOR}" - git config --local user.name "${GITHUB_ACTOR}@users.noreply.github.com" - - name: Merge staging to develop + git config --local user.email "Blueprint-Automation@users.noreply.github.com" + git config --local user.name "GitHub Actions # Blueprint-Automation" + - name: Merge 'master' to 'staging' + id: merge + continue-on-error: true + run: | + git fetch --unshallow + git checkout staging + git pull + git merge --no-ff origin/master -m "Automerge 'master' to 'staging'" + git push + - name: Abort merge + if: steps.merge.outcome == 'failure' + run: git merge --abort + - name: Create Pull Request on merge failure + if: steps.merge.outcome == 'failure' + uses: repo-sync/pull-request@v2 + with: + source_branch: master + destination_branch: staging + pr_title: "Automerge Failed: master -> staging" + pr_body: Failed to merge 'master' into 'staging'. + github_token: ${{ secrets.GITHUB_TOKEN }} + + merge-staging-to-develop: + name: Merge Staging to Develop + runs-on: ubuntu-latest + needs: merge-master-to-staging + steps: + - uses: actions/checkout@v3 + - name: Set Git config + run: | + git config --local user.email "Blueprint-Automation@users.noreply.github.com" + git config --local user.name "GitHub Actions # Blueprint-Automation" + - name: Merge 'staging' to 'develop' + id: merge + continue-on-error: true run: | git fetch --unshallow git checkout develop git pull - git merge --no-ff origin/staging -m "Auto-merge staging to develop" + git merge --no-ff origin/staging -m "Automerge 'staging' to 'develop'." git push + - name: Abort merge + if: steps.merge.outcome == 'failure' + run: git merge --abort + - name: Create Pull Request on merge failure + if: steps.merge.outcome == 'failure' + uses: repo-sync/pull-request@v2 + with: + source_branch: staging + destination_branch: develop + pr_title: "Automerge Failed: staging -> develop" + pr_body: Failed to merge 'staging' into 'develop'. + github_token: ${{ secrets.GITHUB_TOKEN }} + diff --git a/config/webpack.config.js b/config/webpack.config.js index 356e5a979..3a906fb08 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -6,6 +6,8 @@ const pkg = require('../package.json') const { GetEntrypointsForBundle, BlueprintEntrypoints } = require('../scripts/blueprint-map') const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin') +const BLUEPRINTS_INTEGRATION_PACKAGE = '@sofie-automation/blueprints-integration' + module.exports = env => { if (!env) env = {} @@ -20,15 +22,15 @@ module.exports = env => { versionStr = () => JSON.stringify(pkg.version + '+dev-' + moment().format('YYYYMMDD-HHmm')) } - let versionIntegration = pkg.dependencies['@tv2media/blueprints-integration'] + let versionIntegration = pkg.dependencies[BLUEPRINTS_INTEGRATION_PACKAGE] - if (!versionIntegration) throw Error('@tv2media/blueprints-integration version missing!') + if (!versionIntegration) throw Error(`${BLUEPRINTS_INTEGRATION_PACKAGE} version missing!`) // versionTSRTypes = versionTSRTypes.replace(/[^\d.]/g, '') || '0.0.0' // versionIntegration = versionIntegration.replace(/[^\d.]/g, '') || '0.0.0' versionTSRTypes = '1.3.0' - versionIntegration = '42.0.0' + versionIntegration = '46.1.0' const entrypoints = env.bundle ? GetEntrypointsForBundle(env.bundle) : BlueprintEntrypoints diff --git a/jest.config.js b/jest.config.js index 313d6a6b1..03c247db5 100644 --- a/jest.config.js +++ b/jest.config.js @@ -37,6 +37,7 @@ module.exports = { ], moduleDirectories: [ "node_modules", - "src" + "src", + "src/types" ] } diff --git a/package.json b/package.json index fa692afbe..dcb60d610 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tv2-sofie-blueprints-inews", - "version": "1.7.5", + "version": "1.7.8", "repository": "https://github.com/olzzon/tv2-sofie-blueprints-inews", "license": "MIT", "private": true, @@ -60,7 +60,7 @@ "webpack-cli": "^3.1.2" }, "dependencies": { - "@tv2media/blueprints-integration": "1.42.7", + "@sofie-automation/blueprints-integration": "npm:@tv2media/blueprints-integration@46.1.0", "underscore": "^1.12.1" }, "resolutions": { diff --git a/rundowns/offtubes-reference.json b/rundowns/offtubes-reference.json index 565ecb518..95e831f70 100644 --- a/rundowns/offtubes-reference.json +++ b/rundowns/offtubes-reference.json @@ -229,6 +229,50 @@ }, "parts": [] }, + { + "externalId": "00000000:00000000:00000099", + "name": "VCP OVL", + "rank": 2, + "payload": { + "rundownId": "NYHEDERNE-TEST.SOFIE.OFF-TUBES", + "iNewsStory": { + "fields" : { + "pageNumber" : "03", + "title" : "VCP OVL", + "audioTime" : "0", + "totalTime" : "0", + "modifyDate" : "1582890240", + "modifyBy" : "bede", + "ready" : "KLAR", + "runsTime" : "0", + "typecode" : "spx", + "programtitle" : " " + }, + "meta" : { + "rate" : "165" + }, + "cues" : [ + [ + "#cg4 pilotdata", + "LgfxWeb/WEB_HEN_FORMEL1_10AUGT12346_JACH/Mosart=L|00:00|S", + "VCPID=2598145", + "ContinueCount=-1", + "LgfxWeb/WEB_HEN_FORMEL1_10AUGT12346_JACH/Mosart=L|00:00|S" + ] + ], + "id" : "00000000:00000000:00000099", + "body" : "\r\nKAM 1\r\n

\r\n", + "fileId" : "00000000:00000000:00000099", + "identifier" : "00000099" + }, + "modified": "2019-10-11T06:38:00.000Z", + "externalId": "00000000:00000000:00000099", + "rank": 2, + "name": "VCP OVL", + "float": false + }, + "parts": [] + }, { "externalId": "00000000:00000000:00000003", "name": "JINGLE1", diff --git a/scripts/bundle.ts b/scripts/bundle.ts index a65782e18..aab6b351f 100644 --- a/scripts/bundle.ts +++ b/scripts/bundle.ts @@ -1,7 +1,7 @@ -import { BlueprintManifestSet } from '@tv2media/blueprints-integration' import * as fs from 'fs' import * as _ from 'underscore' import * as util from 'util' +import { BlueprintManifestSet } from '../src/types/blueprints-integration' const { BlueprintBundles } = require('./blueprint-map') const readFile = util.promisify(fs.readFile) diff --git a/shelf-layouts/Kommentator.json b/shelf-layouts/Kommentator.json index a38310348..23ee60f43 100644 --- a/shelf-layouts/Kommentator.json +++ b/shelf-layouts/Kommentator.json @@ -112,7 +112,7 @@ { "_id": "YC7RNPTbkXd5wnagp", "type": "filter", - "name": "KG ELEMENTER", + "name": "OVERLAY ELEMENTER", "currentSegment": false, "displayStyle": "list", "rank": 0, @@ -127,7 +127,8 @@ "studio0_graphicsIdent", "studio0_graphicsIdent_persistent", "studio0_graphicsTop", - "studio0_graphicsLower" + "studio0_graphicsLower", + "studio0_pilotOverlay" ], "tags": [ "kommentator" @@ -160,22 +161,6 @@ "showThumbnailsInList": true, "toggleOnSingleClick": true }, - { - "_id": "LiFso7gPYn2SPwHwg", - "type": "external_frame", - "name": "Mic tally", - "currentSegment": false, - "displayStyle": "buttons", - "rank": 0, - "rundownBaseline": false, - "default": false, - "x": 0, - "y": 0, - "width": 22, - "height": 7, - "url": "https://sisyfos.sofsrv04-od.tv2.local?view=mic-tally", - "scale": 0 - }, { "_id": "6GDpdq547HjjZL9YK", "type": "adlib_region", @@ -418,23 +403,46 @@ "showPartTitle": true }, { - "_id" : "jLzHen2LoGEMxE68N", - "type" : "mini_rundown", - "name" : "Mini rundown", - "currentSegment" : false, - "displayStyle" : "buttons", - "rank" : 0, - "rundownBaseline" : false, - "showThumbnailsInList" : false, - "hideDuplicates" : false, - "default" : false, - "nextInCurrentPart" : false, - "oneNextPerSourceLayer" : false, - "x" : 7, - "y" : 0, - "width" : 14, - "height" : 7, - "scale" : 0 + "_id": "h9xDp3HvzLaSo4yJi", + "type": "mini_rundown", + "name": "Mini rundown", + "currentSegment": false, + "displayStyle": "buttons", + "rank": 0, + "rundownBaseline": false, + "showThumbnailsInList": false, + "hideDuplicates": false, + "default": false, + "nextInCurrentPart": false, + "oneNextPerSourceLayer": false, + "x": 3, + "y": 3.8, + "width": 16, + "height": 3, + "scale": 0 + }, + { + "_id": "dkKTHZAwF98aKkD47", + "type": "external_frame", + "name": "Mic tally", + "currentSegment": false, + "displayStyle": "buttons", + "rank": 0, + "rundownBaseline": false, + "showThumbnailsInList": false, + "hideDuplicates": false, + "default": false, + "nextInCurrentPart": false, + "oneNextPerSourceLayer": false, + "url": "http://sofqb06-od:1176/?view=mic-tally", + "x": 3, + "y": 0, + "width": 16, + "height": 5, + "customClasses": [ + "" + ], + "scale": 0 } ], "type": "dashboard_layout", @@ -451,26 +459,27 @@ }, { "_id": "m4ouEduSAvNXm6WZh", - "label": "▲ Previous Segment", + "label": "▲", "type": "move_previous_segment", "x": 0, - "y": 0, - "width": 6, + "y": 4, + "width": 2, "height": 1, "labelToggled": "" }, { "_id": "FgyddcqkKFhSQeMBS", - "label": "▼ Next Segment", + "label": "▼", "type": "move_next_segment", "x": 0, - "y": 2, - "width": 6, + "y": 6, + "width": 2, "height": 1, "labelToggled": "" } ], "exposeAsStandalone": true, + "regionId": "shelf_layouts", "exposeAsShelf": true, "iconColor": "#8e44ad", "icon": { @@ -486,6 +495,5 @@ }, "openByDefault": true, "startingHeight": 80, - "disableContextMenu": true, - "regionId": "shelf_layouts" + "disableContextMenu": true } diff --git a/shelf-layouts/Mini_Shelf_Layout.json b/shelf-layouts/Mini_Shelf_Layout.json index 30d492451..a06c12f44 100644 --- a/shelf-layouts/Mini_Shelf_Layout.json +++ b/shelf-layouts/Mini_Shelf_Layout.json @@ -3,6 +3,7 @@ "type": "dashboard_layout", "icon": "", "iconColor": "#ffffff", + "isDefaultLayout": true, "regionId": "mini_shelf_layouts", "filters": [ { @@ -31,4 +32,4 @@ "toggleOnSingleClick": true } ] -} \ No newline at end of file +} diff --git a/shelf-layouts/Q flow.json b/shelf-layouts/Q flow.json index 15c73cc44..dc615f56a 100644 --- a/shelf-layouts/Q flow.json +++ b/shelf-layouts/Q flow.json @@ -8,13 +8,13 @@ "type": "filter", "name": "ADLIB BUTTONS", "currentSegment": false, - "displayStyle": "list", + "displayStyle": "buttons", "rank": 0, "rundownBaseline": false, "default": false, "x": 0, "y": 0, - "width": -1, + "width": -12, "height": 6, "buttonWidthScale": 1.5, "buttonHeightScale": 1.5, @@ -28,12 +28,11 @@ "studio0_offtube_graphicsHeadline", "studio0_offtube_jingle", "studio0_offtube_dve", - "studio0_selected_clip", - "studio0_selected_voiceover", + "studio0_offtube_clip", + "studio0_offtube_voiceover", "studio0_offtube_graphicsFull", "studio0_offtube_aux_studio_screen", "studio0_graphicsIdent", - "studio0_graphicsIdent_persistent", "studio0_graphicsTop", "studio0_graphicsLower", "studio0_graphicsHeadline", @@ -44,7 +43,13 @@ "studio0_dve", "studio0_clip", "studio0_voiceover", - "studio0_full" + "studio0_full", + "studio0_jingle", + "studio0_dve_adlib", + "studio0_audio_bed", + "studio0_pilotOverlay", + "studio0_pilot", + "studio0_selected_graphicsFull" ], "assignHotKeys": true, "tags": [ @@ -68,14 +73,45 @@ { "_id": "tGynaBdafH5dZnttN", "type": "keyboard_preview", - "name": "New Panel", + "name": "Keyboard Panel", "currentSegment": false, "displayStyle": "list", "rank": 0, "rundownBaseline": false, "default": false, "y": 9, - "x": 0 + "x": 0, + "width": -13.5, + "scale": 0.6, + "height": 20 + }, + { + "_id": "CaGXs2ZdPtFMRM47S", + "type": "filter", + "name": "Static Buttons", + "currentSegment": false, + "displayStyle": "buttons", + "rank": 0, + "rundownBaseline": "only", + "showThumbnailsInList": false, + "hideDuplicates": false, + "default": false, + "x": -1, + "y": 0, + "width": 10, + "height": 22, + "buttonWidthScale": 1.5, + "buttonHeightScale": 1.5, + "sourceLayerIds": [ + "studio0_adlib_graphic_cmd", + "studio0_sisyfos_adlibs", + "studio0_jingle", + "studio0_dsk_cmd", + "studio0_dsk_1_cmd" + ], + "tags": [ + "static_button" + ] } ], "type": "dashboard_layout", @@ -92,5 +128,6 @@ "M464 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM224 416H64V160h160v256zm224 0H288V160h160v256z" ] }, - "iconColor": "#14c942" -} \ No newline at end of file + "iconColor": "#14c942", + "regionId": "shelf_layouts" +} diff --git a/shelf-layouts/Rundown_Header_Layout.json b/shelf-layouts/Rundown_Header_Layout.json index 964c687b0..3e40d02f0 100644 --- a/shelf-layouts/Rundown_Header_Layout.json +++ b/shelf-layouts/Rundown_Header_Layout.json @@ -4,6 +4,7 @@ "type": "dashboard_layout", "icon": "", "iconColor": "#ffffff", + "isDefaultLayout": true, "regionId": "rundown_header_layouts", "actionButtons": [], "filters": [ diff --git a/shelf-layouts/Rundown_View_Layout.json b/shelf-layouts/Rundown_View_Layout.json index df3e63e91..2c56653a6 100644 --- a/shelf-layouts/Rundown_View_Layout.json +++ b/shelf-layouts/Rundown_View_Layout.json @@ -5,6 +5,7 @@ "type": "rundown_view_layout", "icon": "", "iconColor": "#ffffff", + "isDefaultLayout": true, "openByDefault": false, "showBuckets": true, "disableContextMenu": false, @@ -27,4 +28,4 @@ "studio0_clip", "studio0_voiceover" ] -} \ No newline at end of file +} diff --git a/shelf-layouts/Shortcuts and adlib scroll.json b/shelf-layouts/Shortcuts and adlib scroll.json index c70961fb9..e77fea9c4 100755 --- a/shelf-layouts/Shortcuts and adlib scroll.json +++ b/shelf-layouts/Shortcuts and adlib scroll.json @@ -14,7 +14,7 @@ "default": false, "x": 1, "y": 7, - "width": 64.5, + "width": -15.8, "height": 5, "overflowHorizontally": true, "showAsTimeline": true, @@ -41,7 +41,8 @@ "tags": [ "flow_producer" ], - "toggleOnSingleClick": true + "toggleOnSingleClick": true, + "scale": 0 }, { "_id": "s4KkTnsERPNcrkqeD", @@ -55,8 +56,8 @@ "url": "http://10.201.76.12:8005/keyboardmap", "x": 1.2, "y": 18, - "width": 54.3, - "height": 18.5, + "width": 54.8, + "height": 18, "scale": 0.79 }, { @@ -71,7 +72,7 @@ "x": -1, "y": 0, "width": 15.7, - "height": 15.5, + "height": 15, "includeClearInRundownBaseline": false, "assignHotKeys": false, "hide": false, @@ -120,7 +121,7 @@ "sourceLayerIds": [ "studio0_dve" ], - "width": 64.5, + "width": -15.8, "height": 5, "buttonWidthScale": 1.5, "buttonHeightScale": 1.5, @@ -146,7 +147,7 @@ "buttonWidthScale": 1.5, "buttonHeightScale": 1.5, "y": 0, - "width": 64.5, + "width": -15.8, "height": 5, "showAsTimeline": true, "includeClearInRundownBaseline": true, diff --git a/src/__mocks__/context.ts b/src/__mocks__/context.ts index 1473f5ca3..576355bda 100644 --- a/src/__mocks__/context.ts +++ b/src/__mocks__/context.ts @@ -28,7 +28,7 @@ import { PieceLifespan, PlaylistTimingType, Time -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ITV2ActionExecutionContext, PieceMetaData } from 'tv2-common' import { NoteType } from 'tv2-constants' import { defaultShowStyleConfig, defaultStudioConfig } from '../tv2_afvd_showstyle/__tests__/configs' @@ -399,6 +399,10 @@ export class SyncIngestUpdateToPartInstanceContext extends RundownUserContext public notifyUserInfo(_message: string, _params?: { [p: string]: any }): void { // Do nothing } + + public removePartInstance(): void { + // Do nothing + } } // tslint:disable-next-line: max-classes-per-file diff --git a/src/inews-mixins/__tests__/playlist.spec.ts b/src/inews-mixins/__tests__/playlist.spec.ts index 8893fbd80..fb4427b4c 100644 --- a/src/inews-mixins/__tests__/playlist.spec.ts +++ b/src/inews-mixins/__tests__/playlist.spec.ts @@ -4,7 +4,7 @@ import { IngestSegment, IShowStyleUserContext, PlaylistTimingType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { getRundownWithBackTime } from 'inews-mixins' import { ShowStyleUserContext } from '../../__mocks__/context' import { parseConfig as parseShowStyleConfig } from '../../tv2_afvd_showstyle/helpers/config' diff --git a/src/inews-mixins/__tests__/rundownDuration.spec.ts b/src/inews-mixins/__tests__/rundownDuration.spec.ts index 563faa45d..5a1433977 100644 --- a/src/inews-mixins/__tests__/rundownDuration.spec.ts +++ b/src/inews-mixins/__tests__/rundownDuration.spec.ts @@ -1,4 +1,4 @@ -import { IngestSegment } from '@tv2media/blueprints-integration' +import { IngestSegment } from 'blueprints-integration' import { literal } from 'tv2-common' import { getRundownDuration } from '../rundownDuration' diff --git a/src/inews-mixins/playlist.ts b/src/inews-mixins/playlist.ts index 9da91bec0..fa8fb779f 100644 --- a/src/inews-mixins/playlist.ts +++ b/src/inews-mixins/playlist.ts @@ -13,7 +13,7 @@ import { RundownPlaylistTiming, ShowStyleBlueprintManifest, StudioBlueprintManifest -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { assertUnreachable, literal, TimeFromINewsField } from 'tv2-common' import { getRundownDuration } from './rundownDuration' diff --git a/src/inews-mixins/rundownDuration.ts b/src/inews-mixins/rundownDuration.ts index 6340ddb02..654f657db 100644 --- a/src/inews-mixins/rundownDuration.ts +++ b/src/inews-mixins/rundownDuration.ts @@ -1,4 +1,4 @@ -import { IngestSegment } from '@tv2media/blueprints-integration' +import { IngestSegment } from 'blueprints-integration' import { INewsPayload, TimeFromINewsField } from 'tv2-common' export function getRundownDuration(segments: IngestSegment[]) { diff --git a/src/tv2-common/__tests__/EvaluateCueTelemetrics.spec.ts b/src/tv2-common/__tests__/EvaluateCueTelemetrics.spec.ts new file mode 100644 index 000000000..2872926e1 --- /dev/null +++ b/src/tv2-common/__tests__/EvaluateCueTelemetrics.spec.ts @@ -0,0 +1,282 @@ +import { IBlueprintPiece, IShowStyleUserContext, PieceLifespan, TSR } from 'blueprints-integration' +import { CueType, RobotCameraLayer, SharedOutputLayers, SharedSourceLayers } from '../../tv2-constants' +import { EvaluateCueRobotCamera } from '../cues/EvaluateCueRobotCamera' +import { CueDefinitionRobotCamera } from '../inewsConversion' + +describe('EvaluateCueRobotCamera', () => { + let context: IShowStyleUserContext + + beforeEach(() => { + context = ({} as unknown) as IShowStyleUserContext + }) + + it('adds a Robot Camera piece', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition() + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, '') + + expect(pieces).toHaveLength(1) + }) + + function createRobotCameraCueDefinition(presetShot?: number, startTimeInSeconds?: number): CueDefinitionRobotCamera { + return { + type: CueType.RobotCamera, + presetIdentifier: presetShot ?? 1, + iNewsCommand: '', + start: { + seconds: startTimeInSeconds + } + } + } + + it('parse the externalId to the piece', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition() + const externalId: string = 'someExternalId' + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, externalId) + + expect(pieces[0].externalId).toEqual(externalId) + }) + + it('has lifeSpan withinPart', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition() + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, '') + + expect(pieces[0].lifespan).toEqual(PieceLifespan.WithinPart) + }) + + it('creates a telemetrics timeline object', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition() + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, '') + + expect(pieces[0].content.timelineObjects).toHaveLength(1) + const result = pieces[0].content.timelineObjects[0] + expect(result.layer).toEqual(RobotCameraLayer.TELEMETRICS) + expect(result.content.deviceType).toEqual(TSR.DeviceType.TELEMETRICS) + }) + + it('timeline object has start time 0', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition() + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, '') + + expect((pieces[0].content.timelineObjects[0].enable as { start: number }).start).toEqual(0) + }) + + it('has Robot Camera source layer', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition() + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, '') + + expect(pieces[0].sourceLayerId).toEqual(SharedSourceLayers.RobotCamera) + }) + + it('has SEC for output layer', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition() + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, '') + + expect(pieces[0].outputLayerId).toEqual(SharedOutputLayers.SEC) + }) + + it('receives cameraPreset 1, blueprint piece name is Robot[1]', () => { + assertCorrectName(1) + }) + + function assertCorrectName(preset: number): void { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition(preset) + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, '') + + const result: IBlueprintPiece = pieces[0] + expect(result.name).toEqual(`Robot[${preset}]`) + } + + it('receives cameraPreset 2, blueprint piece name is Robot[2]', () => { + assertCorrectName(2) + }) + + it('receives cameraPreset 1, creates a timeline object with presetShotIdentifiers [1]', () => { + assertCorrectShotPreset(1) + }) + + function assertCorrectShotPreset(presetShot: number): void { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition(presetShot) + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, '') + + const result: TSR.TimelineObjTelemetrics = pieces[0].content.timelineObjects[0] as TSR.TimelineObjTelemetrics + expect(result.content.presetShotIdentifiers).toEqual([presetShot]) + } + + it('receives cameraPreset 2, creates a timeline object with presetShotIdentifiers [2]', () => { + assertCorrectShotPreset(2) + }) + + it('starts after 10 seconds, blueprint piece starts after 10.000 ms', () => { + assertStartTime(10) + }) + + function assertStartTime(startTimeInSeconds: number): void { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition(1, startTimeInSeconds) + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, '') + + const result: IBlueprintPiece = pieces[0] + expect(result.enable.start).toEqual(startTimeInSeconds * 1000) + } + + it('starts after 20 seconds, blueprint piece starts after 20.000 ms', () => { + assertStartTime(20) + }) + + it('has duration of one second', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition(1) + const pieces: IBlueprintPiece[] = [] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, '') + + const result: IBlueprintPiece = pieces[0] + expect(result.enable.duration).toEqual(100) + }) + + it('already has a piece with another sourceLayer, creates a new piece', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition() + const pieces: IBlueprintPiece[] = [createRobotCameraBlueprintPiece(SharedSourceLayers.PgmDesign)] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, 'someOtherExternalId') + + expect(pieces.length).toEqual(2) + }) + + function createRobotCameraBlueprintPiece(sourceLayer: SharedSourceLayers, startTimeInMs?: number): IBlueprintPiece { + return { + externalId: '', + name: 'Robot', + enable: { + start: startTimeInMs ?? 0 + }, + lifespan: PieceLifespan.WithinPart, + sourceLayerId: sourceLayer, + outputLayerId: '', + content: { + timelineObjects: [] + } + } + } + + describe('already has a piece with same externalId', () => { + it('has another start time, creates another blueprint piece', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition(1, 20) + + const existingPiece: IBlueprintPiece = createRobotCameraBlueprintPiece(SharedSourceLayers.RobotCamera, 10000) + existingPiece.content.timelineObjects.push(createTelemetricsTimelineObject(2)) + const pieces: IBlueprintPiece[] = [existingPiece] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, 'randomExternalId') + + expect(pieces).toHaveLength(2) + }) + + function createTelemetricsTimelineObject(presetShot?: number): TSR.TimelineObjTelemetrics { + return { + id: '', + enable: { + start: 0 + }, + layer: RobotCameraLayer.TELEMETRICS, + content: { + deviceType: TSR.DeviceType.TELEMETRICS, + presetShotIdentifiers: presetShot ? [presetShot] : [] + } + } + } + + it('has a blueprint piece with the same start time, no new timeline object is created', () => { + const startTime: number = 20 + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition(1, startTime) + + const existingPiece: IBlueprintPiece = createRobotCameraBlueprintPiece( + SharedSourceLayers.RobotCamera, + startTime * 1000 + ) + existingPiece.content.timelineObjects.push(createTelemetricsTimelineObject()) + const pieces: IBlueprintPiece[] = [existingPiece] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, 'randomExternalId') + + expect(pieces[0].content.timelineObjects).toHaveLength(1) + }) + + it('has a blueprint piece with the same start time, existing blueprint piece gets presetShotIdentifier added to timeline object', () => { + const startTime: number = 20 + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition(2, startTime) + + const existingPiece: IBlueprintPiece = createRobotCameraBlueprintPiece( + SharedSourceLayers.RobotCamera, + startTime * 1000 + ) + existingPiece.content.timelineObjects.push(createTelemetricsTimelineObject(1)) + const pieces: IBlueprintPiece[] = [existingPiece] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, 'randomExternalId') + + const timelineObject: TSR.TimelineObjTelemetrics = pieces[0].content + .timelineObjects[0] as TSR.TimelineObjTelemetrics + expect(timelineObject.content.presetShotIdentifiers).toEqual([1, 2]) + }) + + it('has a blueprint piece with same start time and same presetIdentifier, no presetIdentifier is added', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition(1) + + const existingPiece: IBlueprintPiece = createRobotCameraBlueprintPiece(SharedSourceLayers.RobotCamera) + existingPiece.name = 'Robot[1]' + existingPiece.content.timelineObjects.push(createTelemetricsTimelineObject(1)) + const pieces: IBlueprintPiece[] = [existingPiece] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, 'randomExternalId') + + const timelineObject: TSR.TimelineObjTelemetrics = pieces[0].content + .timelineObjects[0] as TSR.TimelineObjTelemetrics + expect(timelineObject.content.presetShotIdentifiers).toEqual([1]) + }) + + it('has a blueprint piece with same start time and same presetIdentifier, no new timeline object is created', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition(1) + + const existingPiece: IBlueprintPiece = createRobotCameraBlueprintPiece(SharedSourceLayers.RobotCamera) + existingPiece.name = 'Robot[1]' + existingPiece.content.timelineObjects.push(createTelemetricsTimelineObject(1)) + const pieces: IBlueprintPiece[] = [existingPiece] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, 'randomExternalId') + + expect(pieces).toHaveLength(1) + }) + + it('has a blueprint piece with same start time, name is updated to reflect presets in the piece', () => { + const cueDefinition: CueDefinitionRobotCamera = createRobotCameraCueDefinition(2) + + const existingPiece: IBlueprintPiece = createRobotCameraBlueprintPiece(SharedSourceLayers.RobotCamera) + existingPiece.name = 'Robot[1]' + existingPiece.content.timelineObjects.push(createTelemetricsTimelineObject(1)) + const pieces: IBlueprintPiece[] = [existingPiece] + + EvaluateCueRobotCamera(context, cueDefinition, pieces, 'randomExternalId') + + expect(existingPiece.name).toEqual('Robot[1,2]') + }) + }) +}) diff --git a/src/tv2-common/__tests__/frame-time.spec.ts b/src/tv2-common/__tests__/frame-time.spec.ts index 4b599af08..fc2bc24db 100644 --- a/src/tv2-common/__tests__/frame-time.spec.ts +++ b/src/tv2-common/__tests__/frame-time.spec.ts @@ -1,6 +1,6 @@ -import { IBlueprintPiece, PieceLifespan } from '@tv2media/blueprints-integration' +import { IBlueprintPiece, PieceLifespan } from 'blueprints-integration' import { CueType, SourceType } from 'tv2-constants' -import { CreateTiming } from '../cueTiming' +import { CreateTimingEnable } from '../cueTiming' import { RemoteType, SourceDefinitionRemote } from '../inewsConversion' import { CueDefinitionEkstern } from '../inewsConversion/converters/ParseCue' import { literal } from '../util' @@ -23,7 +23,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { @@ -44,7 +44,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { @@ -66,7 +66,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { @@ -87,7 +87,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { @@ -108,7 +108,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { @@ -130,7 +130,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { @@ -151,7 +151,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { @@ -171,7 +171,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { @@ -191,7 +191,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { @@ -214,7 +214,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { @@ -238,7 +238,7 @@ describe('CreateTiming', () => { iNewsCommand: '', sourceDefinition: EKSTERN_SOURCE } - const result = CreateTiming(time, 4000) + const result = CreateTimingEnable(time, 4000) expect(result).toEqual( literal>({ enable: { diff --git a/src/tv2-common/__tests__/getshowStyleVariantId.spec.ts b/src/tv2-common/__tests__/getshowStyleVariantId.spec.ts index 4b2e4ed5c..6aa270c04 100644 --- a/src/tv2-common/__tests__/getshowStyleVariantId.spec.ts +++ b/src/tv2-common/__tests__/getshowStyleVariantId.spec.ts @@ -1,4 +1,4 @@ -import { IBlueprintShowStyleVariant, IngestRundown, IStudioUserContext } from '@tv2media/blueprints-integration' +import { IBlueprintShowStyleVariant, IngestRundown, IStudioUserContext } from 'blueprints-integration' import { makeMockAFVDContext } from '../../__mocks__/context' import { getShowStyleVariantId } from '../getShowStyleVariantId' diff --git a/src/tv2-common/__tests__/onTimelineGenerate.spec.ts b/src/tv2-common/__tests__/onTimelineGenerate.spec.ts index 015636d75..2ff4a58e1 100644 --- a/src/tv2-common/__tests__/onTimelineGenerate.spec.ts +++ b/src/tv2-common/__tests__/onTimelineGenerate.spec.ts @@ -1,4 +1,4 @@ -import { IBlueprintPieceDB, IBlueprintResolvedPieceInstance, TSR } from '@tv2media/blueprints-integration' +import { IBlueprintPieceDB, IBlueprintResolvedPieceInstance, TSR } from 'blueprints-integration' import { SisyfosLLAyer } from '../../tv2_afvd_studio/layers' import { createSisyfosPersistedLevelsTimelineObject, diff --git a/src/tv2-common/__tests__/transition-from-string.spec.ts b/src/tv2-common/__tests__/transition-from-string.spec.ts index a3002113a..ec038df8d 100644 --- a/src/tv2-common/__tests__/transition-from-string.spec.ts +++ b/src/tv2-common/__tests__/transition-from-string.spec.ts @@ -1,4 +1,4 @@ -import { TSR } from '@tv2media/blueprints-integration' +import { TSR } from 'blueprints-integration' import { AtemTransitionStyleFromString } from '../atemTransitionStyleFromString' describe('Transition From String', () => { diff --git a/src/tv2-common/__tests__/transitionSettings.spec.ts b/src/tv2-common/__tests__/transitionSettings.spec.ts index cf13871ba..d46184a0b 100644 --- a/src/tv2-common/__tests__/transitionSettings.spec.ts +++ b/src/tv2-common/__tests__/transitionSettings.spec.ts @@ -1,4 +1,4 @@ -import { TSR } from '@tv2media/blueprints-integration' +import { TSR } from 'blueprints-integration' import { PartType } from '../../tv2-constants' import { AtemSourceIndex } from '../../types/atem' import { TV2BlueprintConfig, TV2BlueprintConfigBase, TV2StudioConfigBase } from '../blueprintConfig' diff --git a/src/tv2-common/__tests__/util.spec.ts b/src/tv2-common/__tests__/util.spec.ts index 29d5ea4fd..2093e4404 100644 --- a/src/tv2-common/__tests__/util.spec.ts +++ b/src/tv2-common/__tests__/util.spec.ts @@ -1,6 +1,6 @@ -import { PieceLifespan } from '@tv2media/blueprints-integration' +import { PieceLifespan } from 'blueprints-integration' import { SharedOutputLayers } from 'tv2-constants' -import { assertUnreachable, isAdLibPiece, JoinAssetToFolder, JoinAssetToNetworkPath } from '../util' +import { assertUnreachable, isAdLibPiece, joinAssetToFolder, joinAssetToNetworkPath } from '../util' const JOIN_ASSET_FOLDER_TESTS: Array<{ name: string @@ -192,13 +192,13 @@ describe('util', () => { for (const test of JOIN_ASSET_FOLDER_TESTS) { it(test.name, () => { - expect(JoinAssetToFolder(test.folder, test.assetFile)).toBe(test.result) + expect(joinAssetToFolder(test.folder, test.assetFile)).toBe(test.result) }) } for (const test of JOIN_ASSET_NETWORK_PATH_TESTS) { it(test.name, () => { - expect(JoinAssetToNetworkPath(test.networkPath, test.folder, test.assetFile, test.extensiton)).toBe(test.result) + expect(joinAssetToNetworkPath(test.networkPath, test.folder, test.assetFile, test.extensiton)).toBe(test.result) }) } }) diff --git a/src/tv2-common/actions/actionTypes.ts b/src/tv2-common/actions/actionTypes.ts index 0d0e3c282..cf234bc1e 100644 --- a/src/tv2-common/actions/actionTypes.ts +++ b/src/tv2-common/actions/actionTypes.ts @@ -32,6 +32,7 @@ export interface ActionSelectFullGrafik extends ActionBase { export interface ActionSelectDVE extends ActionBase { type: AdlibActionType.SELECT_DVE config: CueDefinitionDVE + name: string videoId: string | undefined segmentExternalId: string } @@ -47,6 +48,10 @@ export interface ActionSelectJingle extends ActionBase { clip: string } +export interface ActionCallRobotPreset extends ActionBase { + type: AdlibActionType.CALL_ROBOT_PRESET +} + export interface ActionCutToCamera extends ActionBase { type: AdlibActionType.CUT_TO_CAMERA queue: boolean @@ -141,6 +146,7 @@ export type TV2AdlibAction = | ActionSelectDVELayout | ActionSelectFullGrafik | ActionSelectJingle + | ActionCallRobotPreset | ActionCutToCamera | ActionCutToRemote | ActionCommentatorSelectServer diff --git a/src/tv2-common/actions/context.ts b/src/tv2-common/actions/context.ts index e0a8ad5b7..af83548da 100644 --- a/src/tv2-common/actions/context.ts +++ b/src/tv2-common/actions/context.ts @@ -10,7 +10,7 @@ import { IBlueprintResolvedPieceInstance, PackageInfo, Time -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, PartMetaData, PieceMetaData } from 'tv2-common' export interface ITV2ActionExecutionContext extends IActionExecutionContext { diff --git a/src/tv2-common/actions/executeAction.ts b/src/tv2-common/actions/executeAction.ts index 95c2331bd..4b91c92c8 100644 --- a/src/tv2-common/actions/executeAction.ts +++ b/src/tv2-common/actions/executeAction.ts @@ -16,7 +16,7 @@ import { TSR, VTContent, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionClearGraphics, ActionCommentatorSelectDVE, @@ -61,6 +61,7 @@ import { import { AdlibActionType, CueType, + PartType, SharedGraphicLLayer, SharedOutputLayers, SharedSourceLayers, @@ -89,6 +90,7 @@ import { GetTagForLive, GetTagForTransition } from '../pieces' +import { createTelemetricsPieceForRobotCamera } from '../pieces/telemetric' import { findSourceInfo } from '../sources' import { assertUnreachable } from '../util' import { @@ -275,6 +277,15 @@ export async function executeAction< case AdlibActionType.FADE_DOWN_PERSISTED_AUDIO_LEVELS: await executeActionFadeDownPersistedAudioLevels(context, settings) break + case AdlibActionType.CALL_ROBOT_PRESET: { + const preset: number = Number(triggerMode) + if (Number.isNaN(preset)) { + context.notifyUserWarning(`Calling Robot preset ignored. '${triggerMode}' is not a number`) + break + } + await executeActionCallRobotPreset(context, preset) + break + } default: assertUnreachable(actionId) break @@ -591,8 +602,6 @@ async function executeActionSelectDVE< graphicsTemplateContent, parsedCue.sources, settings.DVEGeneratorOptions, - undefined, - false, externalId ) @@ -612,7 +621,7 @@ async function executeActionSelectDVE< let dvePiece: IBlueprintPiece = { externalId, - name: `${parsedCue.template}`, + name: userData.name, enable: { start, ...(end ? { duration: end - start } : {}) @@ -813,6 +822,7 @@ async function executeActionSelectDVELayout< labels: [], iNewsCommand: `DVE=${userData.config.DVEName}` }, + name: userData.config.DVEName, videoId: undefined, segmentExternalId: '' } @@ -1134,8 +1144,7 @@ async function executeActionCutToCamera< input: sourceInfoCam.port, transition: TSR.AtemTransitionStyle.CUT } - }, - classes: ['adlib_deparent'] + } }), ...camSisyfos ]) @@ -1277,8 +1286,7 @@ async function executeActionCutToRemote< input: sourceInfo.port, transition: TSR.AtemTransitionStyle.CUT } - }, - classes: ['adlib_deparent'] + } }), ...eksternSisyfos ]) @@ -1377,8 +1385,6 @@ async function executeActionCutSourceToBox< graphicsTemplateContent, meta.sources, settings.DVEGeneratorOptions, - undefined, - undefined, mediaPlayerSession ) @@ -1849,7 +1855,8 @@ async function executeActionRecallLastLive< originalOnly: true, excludeCurrentPart: false, pieceMetaDataFilter: { - belongsToRemotePart: true + partType: PartType.REMOTE, + pieceExternalId: lastLive.piece.externalId } }) @@ -1903,9 +1910,37 @@ async function executeActionRecallLastDVE< if (lastPlayedScheduledDVE && isLastPlayedAScheduledDVE) { await scheduleLastPlayedDVE(context, settings, actionId, lastPlayedScheduledDVE) - } else { - await scheduleNextScriptedDVE(context, settings, actionId) + await addLatestPieceOnLayerForDve(context, settings.SourceLayers.Ident, actionId, lastPlayedScheduledDVE.piece) + } +} + +async function addLatestPieceOnLayerForDve( + context: ITV2ActionExecutionContext, + layer: string, + actionId: string, + dvePiece: IBlueprintPiece +): Promise { + const lastIdent = await context.findLastPieceOnLayer(layer, { + originalOnly: true, + excludeCurrentPart: false, + pieceMetaDataFilter: { + partType: PartType.DVE, + pieceExternalId: dvePiece.externalId + } + }) + + if (!lastIdent) { + return + } + + const externalId = generateExternalId(context, actionId, [dvePiece.name]) + const newIdentPiece: IBlueprintPiece = { + ...lastIdent.piece, + externalId, + lifespan: PieceLifespan.WithinPart } + + await context.insertPiece('next', newIdentPiece) } async function executeActionFadeDownPersistedAudioLevels< @@ -1927,7 +1962,16 @@ async function executeActionFadeDownPersistedAudioLevels< timelineObjects: [] } } - context.insertPiece('current', resetSisyfosPersistedLevelsPiece) + await context.insertPiece('current', resetSisyfosPersistedLevelsPiece) +} + +async function executeActionCallRobotPreset(context: ITV2ActionExecutionContext, preset: number): Promise { + const robotCameraPiece: IBlueprintPiece = createTelemetricsPieceForRobotCamera( + `callRobotPreset${preset}`, + preset, + 'now' + ) as IBlueprintPiece + await context.insertPiece('current', robotCameraPiece) } async function createFadeSisyfosLevelsMetaData(context: ITV2ActionExecutionContext) { @@ -1971,38 +2015,12 @@ async function scheduleLastPlayedDVE< await executeActionSelectDVE(context, settings, actionId, { type: AdlibActionType.SELECT_DVE, config: lastPlayedDVEMeta.userData.config, + name: lastPlayedDVE.piece.name, segmentExternalId: externalId, videoId: lastPlayedDVEMeta.userData.videoId }) } -async function scheduleNextScriptedDVE< - StudioConfig extends TV2StudioConfigBase, - ShowStyleConfig extends TV2BlueprintConfigBase ->( - context: ITV2ActionExecutionContext, - settings: ActionExecutionSettings, - actionId: string -): Promise { - const nextScriptedDVE: IBlueprintPiece | undefined = await context.findLastScriptedPieceOnLayer( - settings.SourceLayers.DVE - ) - - if (!nextScriptedDVE) { - return - } - - const externalId: string = generateExternalId(context, actionId, [nextScriptedDVE.name]) - const dveMeta: DVEPieceMetaData = nextScriptedDVE.metaData as DVEPieceMetaData - - await executeActionSelectDVE(context, settings, actionId, { - type: AdlibActionType.SELECT_DVE, - config: dveMeta.userData.config, - segmentExternalId: externalId, - videoId: dveMeta.userData.videoId - }) -} - async function executeActionSelectFull< StudioConfig extends TV2StudioConfigBase, ShowStyleConfig extends TV2BlueprintConfigBase @@ -2049,13 +2067,12 @@ async function executeActionSelectFull< iNewsCommand: '' } - const generator = new PilotGraphicGenerator({ + const generator = PilotGraphicGenerator.createPilotGraphicGenerator({ config, context, partId: externalId, settings: settings.pilotGraphicSettings, parsedCue: cue, - engine: 'FULL', segmentExternalId: userData.segmentExternalId, adlib: { rank: 0 } }) @@ -2129,7 +2146,7 @@ async function executeActionClearGraphics< deviceType: TSR.DeviceType.VIZMSE, type: TSR.TimelineContentTypeVizMSE.CLEAR_ALL_ELEMENTS, channelsToSendCommands: userData.sendCommands ? ['OVL1', 'FULL1', 'WALL1'] : undefined, - showId: config.selectedGraphicsSetup.OvlShowId + showId: config.selectedGraphicsSetup.OvlShowName ?? '' // @todo: improve types at the junction of HTML and Viz } }) ] diff --git a/src/tv2-common/atemTransitionStyleFromString.ts b/src/tv2-common/atemTransitionStyleFromString.ts index ecc3552ec..70ad6045a 100644 --- a/src/tv2-common/atemTransitionStyleFromString.ts +++ b/src/tv2-common/atemTransitionStyleFromString.ts @@ -1,4 +1,4 @@ -import { TSR } from '@tv2media/blueprints-integration' +import { TSR } from 'blueprints-integration' export function AtemTransitionStyleFromString(str: string): TSR.AtemTransitionStyle { if (str.match(/MIX/i)) { diff --git a/src/tv2-common/blueprintConfig.ts b/src/tv2-common/blueprintConfig.ts index 37bfb4f45..622e9d573 100644 --- a/src/tv2-common/blueprintConfig.ts +++ b/src/tv2-common/blueprintConfig.ts @@ -1,4 +1,4 @@ -import { TableConfigItemValue } from '@tv2media/blueprints-integration' +import { TableConfigItemValue } from 'blueprints-integration' import { TableConfigItemDSK, TableConfigItemSourceMappingWithSisyfos } from 'tv2-common' import { DVEConfigInput } from './helpers' import { SourceInfo } from './sources' @@ -15,7 +15,8 @@ export interface TableConfigItemBreakers { LoadFirstFrame: boolean } -export interface TableConfigItemGFXTemplates { +export interface TableConfigItemGfxTemplate { + /** Name of the Viz Template. For HTML graphics it's the Graphic name. */ VizTemplate: string SourceLayer: string LayerMapping: string @@ -23,26 +24,36 @@ export interface TableConfigItemGFXTemplates { INewsName: string VizDestination: string OutType: string - IsDesign: boolean +} + +export interface TableConfigItemGfxDesignTemplate { + INewsName: string + INewsStyleColumn: string + /** Name of the Viz template trigering design change. For HTML graphics it coresponds to a CSS class. */ + VizTemplate: string +} + +export interface TableConfigItemOverlayShowMapping { + Design: string + GraphicsSetup: string[] + Schema: string[] } export interface TableConfigItemAdLibTransitions { Transition: string } -export interface TableConfigSchema { - schemaName: string - designIdentifier: string - vizTemplateName: string - casparCgDveBgScene: string +export interface TableConfigGfxSchema { + SchemaName: string + INewsSkemaColumn: string + VizTemplate: string } export interface TableConfigGraphicsSetup { Name: string - VcpConcept: string - OvlShowId: string - FullShowId: string - DveLayoutFolder: string + HtmlPackageFolder: string + OvlShowName?: string + FullShowName?: string } export interface TV2StudioConfigBase { @@ -141,12 +152,15 @@ export interface TV2ShowstyleBlueprintConfigBase { CasparCGLoadingClip: string BreakerConfig: TableConfigItemBreakers[] DVEStyles: DVEConfigInput[] - GFXTemplates: TableConfigItemGFXTemplates[] + GFXTemplates: TableConfigItemGfxTemplate[] + GfxDesignTemplates: TableConfigItemGfxDesignTemplate[] Transitions: TableConfigItemAdLibTransitions[] ShowstyleTransition: string MakeAdlibsForFulls: boolean LYDConfig: TableConfigItemValue - SchemaConfig: TableConfigSchema[] + GfxSchemaTemplates: TableConfigGfxSchema[] + GraphicsSetups: TableConfigGraphicsSetup[] + SelectedGraphicsSetupName: string } export interface TV2BlueprintConfigBase diff --git a/src/tv2-common/content/dve.ts b/src/tv2-common/content/dve.ts index 23795d3a8..66e7f40c1 100644 --- a/src/tv2-common/content/dve.ts +++ b/src/tv2-common/content/dve.ts @@ -9,16 +9,15 @@ import { TSR, VTContent, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { createEmptyObject, CueDefinitionDVE, DVEConfigInput, - DVEParentClass, DVESources, FindDSKFullGFX, findSourceInfo, - JoinAssetToFolder, + joinAssetToFolder, literal, PartDefinition, PieceMetaData, @@ -134,9 +133,7 @@ export function MakeContentDVEBase< partDefinition: PartDefinition, parsedCue: CueDefinitionDVE, dveConfig: DVEConfigInput | undefined, - dveGeneratorOptions: DVEOptions, - addClass?: boolean, - adlib?: boolean + dveGeneratorOptions: DVEOptions ): { content: WithTimeline; valid: boolean } { if (!dveConfig) { context.notifyUserWarning(`DVE ${parsedCue.template} is not configured`) @@ -161,8 +158,6 @@ export function MakeContentDVEBase< graphicsTemplateContent, parsedCue.sources, dveGeneratorOptions, - addClass ? DVEParentClass('studio0', dveConfig.DVEName) : undefined, - adlib, partDefinition.segmentExternalId ) } @@ -177,8 +172,6 @@ export function MakeContentDVE2< graphicsTemplateContent: { [key: string]: string }, sources: DVESources | undefined, dveGeneratorOptions: DVEOptions, - className?: string, - adlib?: boolean, mediaPlayerSessionId?: string ): { content: WithTimeline; valid: boolean } { let template: DVEConfig @@ -306,11 +299,11 @@ export function MakeContentDVE2< let frameFile = dveConfig.DVEGraphicsFrame ? dveConfig.DVEGraphicsFrame.toString() : undefined if (keyFile) { - keyFile = JoinAssetToFolder(config.studio.DVEFolder, keyFile) + keyFile = joinAssetToFolder(config.studio.DVEFolder, keyFile) } if (frameFile) { - frameFile = JoinAssetToFolder(config.studio.DVEFolder, frameFile) + frameFile = joinAssetToFolder(config.studio.DVEFolder, frameFile) } return { @@ -338,7 +331,7 @@ export function MakeContentDVE2< type: TSR.TimelineContentTypeAtem.SSRC, ssrc: { boxes } }, - classes: className ? [...classes, className] : classes, + classes, metaData: literal({ mediaPlayerSession: server ? mediaPlayerSessionId ?? MEDIA_PLAYER_AUTO : undefined }) @@ -383,8 +376,7 @@ export function MakeContentDVE2< input: AtemSourceIndex.SSrc, transition: TSR.AtemTransitionStyle.CUT } - }, - ...(adlib ? { classes: ['adlib_deparent'] } : {}) + } }), literal({ id: '', diff --git a/src/tv2-common/content/jingle.ts b/src/tv2-common/content/jingle.ts index 52eeff218..d0463cc45 100644 --- a/src/tv2-common/content/jingle.ts +++ b/src/tv2-common/content/jingle.ts @@ -1,9 +1,9 @@ -import { TimelineObjectCoreExt, TSR, VTContent, WithTimeline } from '@tv2media/blueprints-integration' +import { TimelineObjectCoreExt, TSR, VTContent, WithTimeline } from 'blueprints-integration' import { TimeFromFrames } from 'tv2-common' import { TV2BlueprintConfig, TV2BlueprintConfigBase, TV2StudioConfigBase } from '../blueprintConfig' import { EnableDSK, FindDSKJingle } from '../helpers' import { TimelineBlueprintExt } from '../onTimelineGenerate' -import { JoinAssetToFolder, JoinAssetToNetworkPath, literal } from '../util' +import { joinAssetToFolder, joinAssetToNetworkPath, literal } from '../util' export interface JingleLayers { Caspar: { @@ -26,11 +26,11 @@ export function CreateJingleExpectedMedia( duration: number, alphaAtEnd: number ) { - const fileName = JoinAssetToFolder(config.studio.JingleFolder, jingle) + const fileName = joinAssetToFolder(config.studio.JingleFolder, jingle) return literal>({ fileName, - path: JoinAssetToNetworkPath( + path: joinAssetToNetworkPath( config.studio.JingleNetworkBasePath, config.studio.JingleFolder, jingle, @@ -59,7 +59,7 @@ export function CreateJingleContentBase< alphaAtEnd: number, layers: JingleLayers ) { - const fileName = JoinAssetToFolder(config.studio.JingleFolder, file) + const fileName = joinAssetToFolder(config.studio.JingleFolder, file) const jingleDSK = FindDSKJingle(config) return literal>({ ...CreateJingleExpectedMedia(config, file, alphaAtStart, duration, alphaAtEnd), diff --git a/src/tv2-common/content/server.ts b/src/tv2-common/content/server.ts index 1e5961e17..137586101 100644 --- a/src/tv2-common/content/server.ts +++ b/src/tv2-common/content/server.ts @@ -1,24 +1,11 @@ -import { - IShowStyleUserContext, - TimelineObjectCoreExt, - TSR, - VTContent, - WithTimeline -} from '@tv2media/blueprints-integration' -import { - AddParentClass, - GetSisyfosTimelineObjForServer, - literal, - PartDefinition, - ServerParentClass, - TransitionSettings -} from 'tv2-common' +import { IShowStyleUserContext, TimelineObjectCoreExt, TSR, VTContent, WithTimeline } from 'blueprints-integration' +import { GetSisyfosTimelineObjForServer, literal, PartDefinition, TransitionSettings } from 'tv2-common' import { AbstractLLayer, ControlClasses, GetEnableClassForServer } from 'tv2-constants' import { TV2BlueprintConfig } from '../blueprintConfig' import { TimelineBlueprintExt } from '../onTimelineGenerate' import { ServerContentProps, ServerPartProps } from '../parts' import { AdlibServerOfftubeOptions } from '../pieces' -import { JoinAssetToNetworkPath } from '../util' +import { joinAssetToNetworkPath } from '../util' // TODO: These are TSR layers, not sourcelayers export interface MakeContentServerSourceLayers { @@ -44,7 +31,7 @@ export function GetVTContentProperties( ): VTProps { return literal({ fileName: contentProps.file, - path: JoinAssetToNetworkPath( + path: joinAssetToNetworkPath( config.studio.ClipNetworkBasePath, config.studio.ClipFolder, contentProps.file, @@ -60,7 +47,6 @@ export function GetVTContentProperties( export function MakeContentServer( _context: IShowStyleUserContext, - partDefinition: PartDefinition, config: TV2BlueprintConfig, sourceLayers: MakeContentServerSourceLayers, partProps: ServerPartProps, @@ -69,12 +55,11 @@ export function MakeContentServer( return literal>({ ...GetVTContentProperties(config, contentProps), ignoreMediaObjectStatus: true, - timelineObjects: GetServerTimeline(partDefinition, config, sourceLayers, partProps, contentProps) + timelineObjects: GetServerTimeline(config, sourceLayers, partProps, contentProps) }) } function GetServerTimeline( - partDefinition: PartDefinition, config: TV2BlueprintConfig, sourceLayers: MakeContentServerSourceLayers, partProps: ServerPartProps, @@ -101,12 +86,7 @@ function GetServerTimeline( }, metaData: { mediaPlayerSession: contentProps.mediaPlayerSession - }, - classes: [ - ...(AddParentClass(config, partDefinition) && !partProps.adLibPix - ? [ServerParentClass('studio0', contentProps.file)] - : []) - ] + } } const mediaOffObj = JSON.parse(JSON.stringify(mediaObj)) as TSR.TimelineObjCCGMedia & TimelineBlueprintExt @@ -157,7 +137,6 @@ export function CutToServer( partDefinition: PartDefinition, config: TV2BlueprintConfig, atemLLayerMEPGM: string, - adLib?: boolean, offtubeOptions?: AdlibServerOfftubeOptions ) { return [ @@ -181,10 +160,7 @@ export function CutToServer( metaData: { mediaPlayerSession: mediaPlayerSessionId }, - classes: [ - ...(adLib && !offtubeOptions?.isOfftube ? ['adlib_deparent'] : []), - ...(offtubeOptions?.isOfftube ? [ControlClasses.AbstractLookahead] : []) - ] + classes: [...(offtubeOptions?.isOfftube ? [ControlClasses.AbstractLookahead] : [])] }) ] } diff --git a/src/tv2-common/cueTiming.ts b/src/tv2-common/cueTiming.ts index 168ec0a1c..f1056d286 100644 --- a/src/tv2-common/cueTiming.ts +++ b/src/tv2-common/cueTiming.ts @@ -1,6 +1,6 @@ -import { CueDefinition, CueDefinitionBase, CueTime } from './inewsConversion/converters/ParseCue' +import { CueDefinition, CueTime } from './inewsConversion/converters/ParseCue' -import { IBlueprintAdLibPiece, IBlueprintPiece, PieceLifespan } from '@tv2media/blueprints-integration' +import { IBlueprintPiece, PieceLifespan } from 'blueprints-integration' import { TV2BlueprintConfigBase, TV2StudioConfigBase } from 'tv2-common' const FRAME_TIME = 1000 / 25 // TODO: This should be pulled from config. @@ -16,17 +16,6 @@ export function GetDefaultOut< return 4 * 1000 } -export function CreateTiming( - cue: CueDefinition, - defaultOut: number -): Pick | Pick { - if (cue.adlib) { - return CreateTimingAdLib(cue) - } else { - return CreateTimingEnable(cue, defaultOut) - } -} - export function CreateTimingEnable( cue: CueDefinition, defaultOut?: number @@ -42,7 +31,7 @@ export function CreateTimingEnable( if (cue.end) { if (cue.end.infiniteMode) { - result.lifespan = LifeSpan(cue.end.infiniteMode, PieceLifespan.WithinPart) + result.lifespan = LifeSpan(cue.end.infiniteMode) } else { const end = CalculateTime(cue.end) result.enable.duration = end ? end - result.enable.start : undefined @@ -54,24 +43,7 @@ export function CreateTimingEnable( return result } -export function CreateTimingAdLib(cue: CueDefinitionBase): Pick { - const result: Pick = { - lifespan: PieceLifespan.WithinPart, - expectedDuration: 0 - } - - if (cue.end) { - if (cue.end.infiniteMode) { - result.lifespan = LifeSpan(cue.end.infiniteMode, PieceLifespan.WithinPart) - } else { - result.expectedDuration = CalculateTime(cue.end) - } - } - - return result -} - -export function LifeSpan(mode: 'B' | 'S' | 'O', defaultLifespan: PieceLifespan): PieceLifespan { +export function LifeSpan(mode: 'B' | 'S' | 'O'): PieceLifespan { switch (mode) { case 'B': return PieceLifespan.WithinPart @@ -80,8 +52,6 @@ export function LifeSpan(mode: 'B' | 'S' | 'O', defaultLifespan: PieceLifespan): case 'O': return PieceLifespan.OutOnShowStyleEnd } - - return defaultLifespan } export function CalculateTime(time: CueTime): number | undefined { diff --git a/src/tv2-common/cues/EvaluateCueRobotCamera.ts b/src/tv2-common/cues/EvaluateCueRobotCamera.ts new file mode 100644 index 000000000..5453ff5ad --- /dev/null +++ b/src/tv2-common/cues/EvaluateCueRobotCamera.ts @@ -0,0 +1,53 @@ +import { IBlueprintPiece, IShowStyleUserContext, TSR } from 'blueprints-integration' +import { SharedSourceLayers } from '../../tv2-constants' +import { CalculateTime } from '../cueTiming' +import { CueDefinitionRobotCamera } from '../inewsConversion' +import { createTelemetricsPieceForRobotCamera, ROBOT_CAMERA_NAME_PREFIX } from '../pieces/telemetric' + +export function EvaluateCueRobotCamera( + _context: IShowStyleUserContext, + cueDefinition: CueDefinitionRobotCamera, + pieces: IBlueprintPiece[], + externalId: string +): void { + const startTime: number = cueDefinition.start ? CalculateTime(cueDefinition.start) ?? 0 : 0 + + const existingPiece = findExistingPieceForRobotCameraLayerAndStartTime(pieces, startTime) + if (!existingPiece) { + const newPiece = createTelemetricsPieceForRobotCamera(externalId, cueDefinition.presetIdentifier, startTime) + pieces.push(newPiece) + return + } + if (!containsPresetIdentifier(existingPiece, cueDefinition.presetIdentifier)) { + addPresetIdentifierToTimelineObject(existingPiece, cueDefinition.presetIdentifier) + addPresetIdentifierToPieceName(existingPiece, cueDefinition.presetIdentifier) + } +} + +function findExistingPieceForRobotCameraLayerAndStartTime( + pieces: IBlueprintPiece[], + startTime: number +): IBlueprintPiece | undefined { + return pieces.find( + piece => + piece.sourceLayerId === SharedSourceLayers.RobotCamera && + piece.name.startsWith(ROBOT_CAMERA_NAME_PREFIX) && + piece.enable.start === startTime + ) +} + +function containsPresetIdentifier(piece: IBlueprintPiece, presetIdentifier: number): boolean { + const existingTimelineObject = piece.content.timelineObjects[0] + const timelineObject: TSR.TimelineObjTelemetrics = existingTimelineObject as TSR.TimelineObjTelemetrics + return timelineObject.content.presetShotIdentifiers.includes(presetIdentifier) +} + +function addPresetIdentifierToTimelineObject(piece: IBlueprintPiece, presetIdentifier: number): void { + const existingTimelineObject = piece.content.timelineObjects[0] + const timelineObject: TSR.TimelineObjTelemetrics = existingTimelineObject as TSR.TimelineObjTelemetrics + timelineObject.content.presetShotIdentifiers.push(presetIdentifier) +} + +function addPresetIdentifierToPieceName(piece: IBlueprintPiece, presetIdentifier: number): void { + piece.name = `${piece.name.split(']')[0]},${presetIdentifier}]` +} diff --git a/src/tv2-common/cues/ekstern.ts b/src/tv2-common/cues/ekstern.ts index a10891f19..c81a9f8c5 100644 --- a/src/tv2-common/cues/ekstern.ts +++ b/src/tv2-common/cues/ekstern.ts @@ -8,15 +8,11 @@ import { TimelineObjectCoreExt, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { - AddParentClass, - createEmptyObject, CueDefinitionEkstern, - EksternParentClass, literal, PartDefinition, - PartToParentClass, PieceMetaData, TransitionSettings, TV2BlueprintConfigBase, @@ -126,12 +122,6 @@ export function EvaluateEksternBase< 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: { @@ -147,10 +137,7 @@ export function EvaluateEksternBase< 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) diff --git a/src/tv2-common/cues/index.ts b/src/tv2-common/cues/index.ts index 5e1f8e446..ce29a32cb 100644 --- a/src/tv2-common/cues/index.ts +++ b/src/tv2-common/cues/index.ts @@ -2,3 +2,4 @@ export * from './dve' export * from './ekstern' export * from './lyd' export * from './mixMinus' +export * from './EvaluateCueRobotCamera' diff --git a/src/tv2-common/cues/lyd.ts b/src/tv2-common/cues/lyd.ts index b19456688..b50845e8e 100644 --- a/src/tv2-common/cues/lyd.ts +++ b/src/tv2-common/cues/lyd.ts @@ -8,11 +8,11 @@ import { TimelineObjectCoreExt, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CreateTimingEnable, CueDefinitionLYD, - JoinAssetToFolder, + joinAssetToFolder, literal, PartDefinition, TimeFromFrames @@ -123,7 +123,7 @@ function LydContent( }) } - const filePath = lydType === 'fade' ? file : JoinAssetToFolder(config.studio.AudioBedFolder, file) + const filePath = lydType === 'fade' ? file : joinAssetToFolder(config.studio.AudioBedFolder, file) return literal>({ timelineObjects: literal([ diff --git a/src/tv2-common/cues/mixMinus.ts b/src/tv2-common/cues/mixMinus.ts index abf057a1c..aacb4ce8f 100644 --- a/src/tv2-common/cues/mixMinus.ts +++ b/src/tv2-common/cues/mixMinus.ts @@ -6,7 +6,7 @@ import { TimelineObjectCoreExt, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CueDefinitionMixMinus, findSourceInfo, literal, PartDefinition } from 'tv2-common' import { ControlClasses, SharedATEMLLayer, SharedOutputLayers, SharedSourceLayers } from 'tv2-constants' import { TV2BlueprintConfig } from '../blueprintConfig' diff --git a/src/tv2-common/evaluateCues.ts b/src/tv2-common/evaluateCues.ts index b5191ef41..7d2454486 100644 --- a/src/tv2-common/evaluateCues.ts +++ b/src/tv2-common/evaluateCues.ts @@ -5,8 +5,9 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext, + IShowStyleUserContext, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { assertUnreachable, CueDefinition, @@ -16,7 +17,10 @@ import { CueDefinitionEkstern, CueDefinitionJingle, CueDefinitionLYD, + CueDefinitionRobotCamera, CueDefinitionTelefon, + IsTargetingFull, + IsTargetingOVL, PartDefinition } from 'tv2-common' import { CueType } from 'tv2-constants' @@ -94,7 +98,6 @@ export interface EvaluateCuesShowstyleOptions { context: ISegmentUserContext, config: TV2BlueprintConfig, pieces: IBlueprintPiece[], - adlibPieces: IBlueprintAdLibPiece[], actions: IBlueprintActionManifest[], partDefinition: PartDefinition, parsedCue: CueDefinitionDVE, @@ -104,10 +107,8 @@ export interface EvaluateCuesShowstyleOptions { EvaluateCueAdLib?: ( context: ISegmentUserContext, config: TV2BlueprintConfig, - adLibPieces: IBlueprintAdLibPiece[], actions: IBlueprintActionManifest[], mediaSubscriptions: HackPartMediaObjectSubscription[], - partId: string, parsedCue: CueDefinitionAdLib, partDefinition: PartDefinition, rank: number @@ -173,6 +174,12 @@ export interface EvaluateCuesShowstyleOptions { EvaluateCueProfile?: () => void /** TODO: Mic -> For the future */ EvaluateCueMic?: () => void + EvaluateCueRobotCamera?: ( + context: IShowStyleUserContext, + cueDefinition: CueDefinitionRobotCamera, + pieces: IBlueprintPiece[], + partId: string + ) => void } export interface EvaluateCuesOptions { @@ -205,7 +212,7 @@ export async function EvaluateCuesBase( for (const cue of cues) { if (cue && !SkipCue(cue, options.selectedCueTypes, options.excludeAdlibs, options.adlibsOnly)) { - const shouldAdlib = /* config.showStyle.IsOfftube || */ options.adlib ? true : cue.adlib ? true : false + const shouldAdlib = !!(options.adlib || cue.adlib) const adlib = shouldAdlib ? { rank: adLibRank } : undefined switch (cue.type) { @@ -214,8 +221,8 @@ export async function EvaluateCuesBase( if ( config.studio.PreventOverlayWithFull && GraphicIsPilot(cue) && - cue.target === 'OVL' && - cues.some(c => c.type === CueType.Graphic && GraphicIsPilot(c) && c.target === 'FULL') + IsTargetingOVL(cue.target) && + cues.some(c => c.type === CueType.Graphic && GraphicIsPilot(c) && IsTargetingFull(c.target)) ) { context.notifyUserWarning(`Cannot create overlay graphic with FULL`) break @@ -256,7 +263,6 @@ export async function EvaluateCuesBase( context, config, pieces, - adLibPieces, actions, partDefinition, cue, @@ -265,17 +271,7 @@ export async function EvaluateCuesBase( ) // Always make an adlib for DVEs if (!shouldAdlib) { - showStyleOptions.EvaluateCueDVE( - context, - config, - pieces, - adLibPieces, - actions, - partDefinition, - cue, - true, - adLibRank - ) + showStyleOptions.EvaluateCueDVE(context, config, pieces, actions, partDefinition, cue, true, adLibRank) } } break @@ -284,10 +280,8 @@ export async function EvaluateCuesBase( await showStyleOptions.EvaluateCueAdLib( context, config, - adLibPieces, actions, mediaSubscriptions, - partDefinition.externalId, cue, partDefinition, adLibRank @@ -410,6 +404,11 @@ export async function EvaluateCuesBase( case CueType.UNPAIRED_PILOT: context.notifyUserWarning(`Graphic found without target engine`) break + case CueType.RobotCamera: + if (showStyleOptions.EvaluateCueRobotCamera) { + showStyleOptions.EvaluateCueRobotCamera(context, cue, pieces, partDefinition.externalId) + } + break default: if (cue.type !== CueType.Profile && cue.type !== CueType.Mic && cue.type !== CueType.UNKNOWN) { // TODO: Profile -> Change the profile as defined in VIZ device settings @@ -459,13 +458,14 @@ export async function EvaluateCuesBase( }) } } else if (obj.content.type === TSR.TimelineContentTypeVizMSE.CLEAR_ALL_ELEMENTS) { + const o = obj as TSR.TimelineObjVIZMSEClearAllElements piece.expectedPlayoutItems.push({ deviceSubType: TSR.DeviceType.VIZMSE, content: { templateName: 'altud', channel: 'OVL1', templateData: [], - showId: config.selectedGraphicsSetup.OvlShowId + showId: o.content.showId } }) } diff --git a/src/tv2-common/getSegment.ts b/src/tv2-common/getSegment.ts index 4593e333b..002c58334 100644 --- a/src/tv2-common/getSegment.ts +++ b/src/tv2-common/getSegment.ts @@ -4,7 +4,7 @@ import { IBlueprintSegment, IngestSegment, IShowStyleUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { assertUnreachable, GetNextPartCue, diff --git a/src/tv2-common/getShowStyleVariantId.ts b/src/tv2-common/getShowStyleVariantId.ts index 88009484e..35a684b2b 100644 --- a/src/tv2-common/getShowStyleVariantId.ts +++ b/src/tv2-common/getShowStyleVariantId.ts @@ -1,4 +1,4 @@ -import { IBlueprintShowStyleVariant, IngestRundown, IStudioUserContext } from '@tv2media/blueprints-integration' +import { IBlueprintShowStyleVariant, IngestRundown, IStudioUserContext } from 'blueprints-integration' const DEFAULT_VARIANT_NAME = 'default' diff --git a/src/tv2-common/helpers/__tests__/serverResume.spec.ts b/src/tv2-common/helpers/__tests__/serverResume.spec.ts index feb317794..d96f25f27 100644 --- a/src/tv2-common/helpers/__tests__/serverResume.spec.ts +++ b/src/tv2-common/helpers/__tests__/serverResume.spec.ts @@ -5,7 +5,7 @@ import { SplitsContent, VTContent, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { DVEPieceMetaData, literal, PieceMetaData, RemoteType, SourceDefinitionRemote } from 'tv2-common' import { SharedSourceLayers, SourceType } from 'tv2-constants' import { getServerPositionForPartInstance } from '../serverResume' @@ -41,7 +41,7 @@ describe('Server Resume', () => { partInstanceId: 'mock_1', resolvedStart: 1000, resolvedDuration: 10000, - dynamicallyInserted: 1, + dynamicallyInserted: { time: 1 }, piece: { _id: '', enable: { start: 'now' }, @@ -69,7 +69,7 @@ describe('Server Resume', () => { partInstanceId: 'mock_1', startedPlayback: 1000, resolvedStart: 2000, - dynamicallyInserted: 1, + dynamicallyInserted: { time: 1 }, piece: { _id: '', enable: { start: 'now' }, @@ -109,7 +109,7 @@ describe('Server Resume', () => { _id: '', partInstanceId: 'mock_1', resolvedStart: 1000, - dynamicallyInserted: 1, + dynamicallyInserted: { time: 1 }, piece: { _id: '', enable: { start: 'now' }, @@ -155,7 +155,7 @@ describe('Server Resume', () => { _id: '', partInstanceId: 'mock_1', resolvedStart: 1000, - dynamicallyInserted: 1, + dynamicallyInserted: { time: 1 }, piece: { _id: '', enable: { start: 'now' }, diff --git a/src/tv2-common/helpers/__tests__/sisyfos.spec.ts b/src/tv2-common/helpers/__tests__/sisyfos.spec.ts index 47d4f3f80..b47f8ba90 100644 --- a/src/tv2-common/helpers/__tests__/sisyfos.spec.ts +++ b/src/tv2-common/helpers/__tests__/sisyfos.spec.ts @@ -1,4 +1,4 @@ -import { SourceLayerType, TSR } from '@tv2media/blueprints-integration' +import { SourceLayerType, TSR } from 'blueprints-integration' import { GetSisyfosTimelineObjForCamera, GetSisyfosTimelineObjForRemote, diff --git a/src/tv2-common/helpers/abPlayback.ts b/src/tv2-common/helpers/abPlayback.ts index db086d373..4b6de3bc6 100644 --- a/src/tv2-common/helpers/abPlayback.ts +++ b/src/tv2-common/helpers/abPlayback.ts @@ -3,7 +3,7 @@ import { ITimelineEventContext, OnGenerateTimelineObj, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AbstractLLayer, MEDIA_PLAYER_AUTO, MediaPlayerClaimType } from 'tv2-constants' import * as _ from 'underscore' import { TV2BlueprintConfigBase, TV2StudioConfigBase } from '../blueprintConfig' diff --git a/src/tv2-common/helpers/config.ts b/src/tv2-common/helpers/config.ts index 92db76880..25af5f817 100644 --- a/src/tv2-common/helpers/config.ts +++ b/src/tv2-common/helpers/config.ts @@ -1,3 +1,6 @@ +import { ICommonContext } from 'blueprints-integration' +import { TableConfigGraphicsSetup, TV2ShowstyleBlueprintConfigBase } from 'tv2-common' + export interface DVEConfigInput { // _id: string DVEName: string @@ -8,3 +11,18 @@ export interface DVEConfigInput { DVEGraphicsFrame: string // [key: string]: BasicConfigItemValue } + +export function findGraphicsSetup( + context: ICommonContext, + config: ShowStyleConfig, + fallbackGraphicsSetup: ShowStyleConfig['GraphicsSetups'][0] +): ShowStyleConfig['GraphicsSetups'][0] { + const foundTableConfigGraphicsSetup: TableConfigGraphicsSetup | undefined = config.GraphicsSetups.find( + tableConfigGraphicsSetup => tableConfigGraphicsSetup.Name === config.SelectedGraphicsSetupName + ) + if (!foundTableConfigGraphicsSetup) { + context.logWarning(`No graphics setup found for profile: ${config.SelectedGraphicsSetupName}`) + return fallbackGraphicsSetup + } + return foundTableConfigGraphicsSetup +} diff --git a/src/tv2-common/helpers/dsk.ts b/src/tv2-common/helpers/dsk.ts index bbf628afe..ede3d2d5d 100644 --- a/src/tv2-common/helpers/dsk.ts +++ b/src/tv2-common/helpers/dsk.ts @@ -5,7 +5,7 @@ import { PieceLifespan, TableConfigItemValue, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AtemLLayerDSK, literal, SourceLayerAtemDSK } from 'tv2-common' import { AdlibTags, DSKRoles, SharedOutputLayers } from 'tv2-constants' import { ATEMModel } from '../../types/atem' diff --git a/src/tv2-common/helpers/graphics/InternalGraphic.ts b/src/tv2-common/helpers/graphics/InternalGraphic.ts index 28218ea4b..d28c68612 100644 --- a/src/tv2-common/helpers/graphics/InternalGraphic.ts +++ b/src/tv2-common/helpers/graphics/InternalGraphic.ts @@ -1,7 +1,6 @@ -import { IBlueprintAdLibPiece, IBlueprintPiece, PieceLifespan } from '@tv2media/blueprints-integration' -import { Adlib } from 'tv2-common' +import { IBlueprintAdLibPiece, IBlueprintPiece, IShowStyleUserContext, PieceLifespan } from 'blueprints-integration' import _ = require('underscore') -import { AdlibTags, GraphicEngine, PartType, SharedOutputLayers, SharedSourceLayers } from '../../../tv2-constants' +import { AdlibTags, GraphicEngine, SharedOutputLayers, SharedSourceLayers } from '../../../tv2-constants' import { TV2BlueprintConfig } from '../../blueprintConfig' import { CueDefinitionGraphic, GraphicInternal, PartDefinition } from '../../inewsConversion' import { GraphicPieceMetaData, PieceMetaData } from '../../onTimelineGenerate' @@ -15,9 +14,9 @@ import { GetInternalGraphicContentVIZ } from './viz' export class InternalGraphic { public mappedTemplate: string private readonly config: TV2BlueprintConfig + private readonly context: IShowStyleUserContext private readonly parsedCue: CueDefinitionGraphic private readonly partDefinition?: PartDefinition - private readonly adlib?: Adlib private readonly engine: GraphicEngine private readonly name: string private readonly sourceLayerId: SharedSourceLayers @@ -28,8 +27,8 @@ export class InternalGraphic { public constructor( config: TV2BlueprintConfig, + context: IShowStyleUserContext, parsedCue: CueDefinitionGraphic, - adlib?: Adlib, partId?: string, partDefinition?: PartDefinition ) { @@ -38,9 +37,9 @@ export class InternalGraphic { const sourceLayerId = GetSourceLayerForGraphic(config, mappedTemplate) this.config = config + this.context = context this.parsedCue = parsedCue this.partDefinition = partDefinition - this.adlib = adlib this.mappedTemplate = mappedTemplate this.engine = parsedCue.target this.name = GraphicDisplayName(config, parsedCue) @@ -112,7 +111,8 @@ export class InternalGraphic { sisyfosPersistMetaData: { sisyfosLayers: [] }, - belongsToRemotePart: this.partDefinition?.type === PartType.REMOTE + partType: this.partDefinition?.type, + pieceExternalId: this.partDefinition?.externalId }, content: _.clone(this.content) } @@ -120,21 +120,7 @@ export class InternalGraphic { private getInternalGraphicContent(): IBlueprintPiece['content'] { return this.config.studio.GraphicsType === 'HTML' - ? GetInternalGraphicContentCaspar( - this.config, - this.engine, - this.parsedCue, - this.partDefinition, - this.mappedTemplate, - !!this.adlib - ) - : GetInternalGraphicContentVIZ( - this.config, - this.engine, - this.parsedCue, - this.partDefinition, - this.mappedTemplate, - !!this.adlib - ) + ? GetInternalGraphicContentCaspar(this.config, this.engine, this.parsedCue, this.mappedTemplate) + : GetInternalGraphicContentVIZ(this.config, this.context, this.engine, this.parsedCue, this.mappedTemplate) } } diff --git a/src/tv2-common/helpers/graphics/caspar/__tests__/htmlPilotGraphicGenerator.spec.ts b/src/tv2-common/helpers/graphics/caspar/__tests__/htmlPilotGraphicGenerator.spec.ts new file mode 100644 index 000000000..77edb718b --- /dev/null +++ b/src/tv2-common/helpers/graphics/caspar/__tests__/htmlPilotGraphicGenerator.spec.ts @@ -0,0 +1,193 @@ +import { IBlueprintRundownDB, PieceLifespan, PlaylistTimingType, TSR } from 'blueprints-integration' +import { CueDefinitionGraphic, GraphicPilot, HtmlPilotGraphicGenerator, literal } from 'tv2-common' +import { CueType, SharedGraphicLLayer } from 'tv2-constants' +import { SegmentUserContext } from '../../../../../__mocks__/context' +import { defaultShowStyleConfig, defaultStudioConfig } from '../../../../../tv2_afvd_showstyle/__tests__/configs' +import { getConfig, parseConfig as parseShowStyleConfig } from '../../../../../tv2_afvd_showstyle/helpers/config' +import { parseConfig as parseStudioConfig } from '../../../../../tv2_afvd_studio/helpers/config' +import mappingsDefaults from '../../../../../tv2_afvd_studio/migrations/mappings-defaults' +import { pilotGeneratorSettingsOfftube } from '../../../../../tv2_offtube_showstyle/cues/OfftubeGraphics' + +const RUNDOWN_EXTERNAL_ID = 'TEST.SOFIE.JEST' +function makeMockContext() { + const rundown = literal({ + externalId: RUNDOWN_EXTERNAL_ID, + name: RUNDOWN_EXTERNAL_ID, + _id: '', + showStyleVariantId: '', + timing: { + type: PlaylistTimingType.None + } + }) + const mockContext = new SegmentUserContext( + 'test', + mappingsDefaults, + parseStudioConfig, + parseShowStyleConfig, + rundown._id + ) + mockContext.studioConfig = defaultStudioConfig as any + mockContext.showStyleConfig = defaultShowStyleConfig as any + return mockContext +} + +function makeGenerator(cue: CueDefinitionGraphic) { + const context = makeMockContext() + const config = getConfig(context) + const generator = new HtmlPilotGraphicGenerator({ + config, + context, + partId: 'part01', + parsedCue: cue, + segmentExternalId: '', + settings: pilotGeneratorSettingsOfftube + }) + return generator +} + +function makeGeneratorForOvl() { + return makeGenerator({ + type: CueType.Graphic, + target: 'OVL', + graphic: { + type: 'pilot', + name: 'SomeString/MY_PILOT_NAME', + vcpid: 654321, + continueCount: -1 + }, + iNewsCommand: '' + }) +} + +function makeGeneratorForFull() { + return makeGenerator({ + type: CueType.Graphic, + target: 'FULL', + graphic: { + type: 'pilot', + name: 'MY_PILOT_NAME', + vcpid: 654321, + continueCount: -1 + }, + iNewsCommand: '' + }) +} + +describe('HtmlPilotGraphicGenerator', () => { + describe('OVL target', () => { + it('Uses folder and scene name as fileName', () => { + const generator = makeGeneratorForOvl() + const pilotContent = generator.getContent() + expect(pilotContent.fileName).toBe('pilot-images/MY_PILOT_NAME') + }) + it('Makes a path including share, fileName and extension', () => { + const generator = makeGeneratorForOvl() + const pilotContent = generator.getContent() + expect(pilotContent.path).toBe('networkshare\\somefolder\\pilot-images\\MY_PILOT_NAME.png') + }) + it('Makes a template timeline object', () => { + const generator = makeGeneratorForOvl() + const pilotContent = generator.getContent() + const timelineObjects = pilotContent.timelineObjects.filter( + tlObject => + tlObject.content.deviceType === TSR.DeviceType.CASPARCG && + (tlObject as TSR.TimelineObjCCGTemplate).content.type === TSR.TimelineContentTypeCasparCg.TEMPLATE + ) + expect(timelineObjects.length).toBe(1) + expect(timelineObjects[0].layer).toBe(SharedGraphicLLayer.GraphicLLayerOverlayPilot) + expect(timelineObjects[0].content).toMatchObject( + literal>({ + templateType: 'html', + name: 'html-package-folder/index', + data: { + display: 'program', + slots: { + '260_overlay': { + payload: { + type: 'overlay', + url: encodeURI('E:\\\\somepath\\\\pilot-images\\\\MY_PILOT_NAME.png'), + noAnimation: false + }, + display: 'program' + } + } + }, + useStopCommand: false, + mixer: { + opacity: 100 + } + }) + ) + }) + it('Enables a DSK', () => { + const generator = makeGeneratorForOvl() + const pilotContent = generator.getContent() + const timelineObjects = pilotContent.timelineObjects.filter( + tlObject => + tlObject.content.deviceType === TSR.DeviceType.ATEM && + (tlObject as TSR.TimelineObjAtemDSK).content.type === TSR.TimelineContentTypeAtem.DSK + ) + expect(timelineObjects.length).toBe(1) + expect((timelineObjects[0] as TSR.TimelineObjAtemDSK).content.dsk.onAir).toBe(true) + }) + it('Applies cue timing', () => { + const generator = makeGenerator({ + type: CueType.Graphic, + target: 'OVL', + graphic: { + type: 'pilot', + name: 'SomeString/MY_PILOT_NAME', + vcpid: 654321, + continueCount: -1 + }, + start: { seconds: 10 }, + end: { infiniteMode: 'S' }, + iNewsCommand: '' + }) + const pilotPiece = generator.createPiece() + expect(pilotPiece.enable).toEqual({ start: 10000 }) + expect(pilotPiece.lifespan).toBe(PieceLifespan.OutOnSegmentEnd) + }) + }) + describe('FULL target', () => { + it('Makes a path including share, fileName and extension', () => { + const generator = makeGeneratorForFull() + const pilotContent = generator.getContent() + expect(pilotContent.path).toBe('networkshare\\somefolder\\pilot-images\\MY_PILOT_NAME.png') + }) + it('Makes a template timeline object', () => { + const generator = makeGeneratorForFull() + const pilotContent = generator.getContent() + const timelineObjects = pilotContent.timelineObjects.filter( + tlObject => + tlObject.content.deviceType === TSR.DeviceType.CASPARCG && + (tlObject as TSR.TimelineObjCCGTemplate).content.type === TSR.TimelineContentTypeCasparCg.TEMPLATE + ) + expect(timelineObjects.length).toBe(1) + expect(timelineObjects[0].layer).toBe(SharedGraphicLLayer.GraphicLLayerPilot) + expect(timelineObjects[0].content).toMatchObject( + literal>({ + templateType: 'html', + name: 'html-package-folder/index', + data: { + display: 'program', + slots: { + '250_full': { + payload: { + type: 'still', + url: encodeURI('E:\\\\somepath\\\\pilot-images\\\\MY_PILOT_NAME.png'), + noAnimation: false + }, + display: 'program' + } + } + }, + useStopCommand: false, + mixer: { + opacity: 100 + } + }) + ) + }) + }) +}) diff --git a/src/tv2-common/helpers/graphics/caspar/index.ts b/src/tv2-common/helpers/graphics/caspar/index.ts index 96b34ce8b..0dd7a1250 100644 --- a/src/tv2-common/helpers/graphics/caspar/index.ts +++ b/src/tv2-common/helpers/graphics/caspar/index.ts @@ -1,105 +1,114 @@ export * from './slotMappings' -import { - GraphicsContent, - IBlueprintPiece, - IShowStyleUserContext, - TSR, - WithTimeline -} from '@tv2media/blueprints-integration' +import { GraphicsContent, IBlueprintPiece, TSR, WithTimeline } from 'blueprints-integration' import { CueDefinitionGraphic, + GetEnableForGraphic, + GetTimelineLayerForGraphic, GraphicInternal, - GraphicPilot, - JoinAssetToFolder, - JoinAssetToNetworkPath, + joinAssetToFolder, + joinAssetToNetworkPath, literal, - PartDefinition, + PilotGraphicProps, TimelineBlueprintExt, TV2BlueprintConfig } from 'tv2-common' import { GraphicEngine, SharedGraphicLLayer } from 'tv2-constants' -import { GetEnableForGraphic, GetTimelineLayerForGraphic } from '..' import { EnableDSK } from '../../dsk' -import { IsTargetingFull, IsTargetingWall } from '../target' +import { PilotGraphicGenerator } from '../pilot' +import { IsTargetingFull } from '../target' import { layerToHTMLGraphicSlot, Slots } from './slotMappings' export interface CasparPilotGeneratorSettings { - createPilotTimelineForStudio(config: TV2BlueprintConfig, context: IShowStyleUserContext): TSR.TSRTimelineObj[] + createFullPilotTimelineForStudio(config: TV2BlueprintConfig): TSR.TSRTimelineObj[] } export function GetInternalGraphicContentCaspar( config: TV2BlueprintConfig, engine: GraphicEngine, parsedCue: CueDefinitionGraphic, - partDefinition: PartDefinition | undefined, - mappedTemplate: string, - adlib: boolean + mappedTemplate: string ): IBlueprintPiece['content'] { return { - timelineObjects: CasparOverlayTimeline(config, engine, parsedCue, partDefinition, mappedTemplate, adlib) + timelineObjects: CasparOverlayTimeline(config, engine, parsedCue, mappedTemplate) } } -export function GetPilotGraphicContentCaspar( - config: TV2BlueprintConfig, - context: IShowStyleUserContext, - 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 = { - display: 'program', - slots: { - '250_full': { - payload: { - type: 'still', - url: encodeURI( - `${config.studio.HTMLGraphics.GraphicURL}\\${fileName}${config.studio.GraphicFileExtension}` - .replace(/\//g, '\\') // Replace forward slash with backward slash - .replace(/\\/g, '\\\\') // Replace every \ with \\ and encodURI. Double backslash means the HTML template will be able to parse the string correctly. encodeURI so Caspar doesn't mangle the data. - ) +export class HtmlPilotGraphicGenerator extends PilotGraphicGenerator { + private readonly layerMappingName + + constructor(graphicProps: PilotGraphicProps) { + super(graphicProps) + this.layerMappingName = this.getLayerMappingName() + } + public getContent(): WithTimeline { + const graphicFolder = this.config.studio.GraphicFolder ? `${this.config.studio.GraphicFolder}\\` : '' + const sceneName = this.getSceneName() + const fileName = joinAssetToFolder(this.config.studio.GraphicFolder, sceneName) + const absoluteFilePath = `${this.config.studio.HTMLGraphics.GraphicURL}\\${fileName}${this.config.studio.GraphicFileExtension}` + const payloadType = IsTargetingFull(this.engine) ? 'still' : 'overlay' + const templateData = { + display: 'program', + slots: { + [layerToHTMLGraphicSlot[this.layerMappingName]]: { + payload: { + type: payloadType, + url: encodeURI( + absoluteFilePath + + .replace(/\//g, '\\') // Replace forward slash with backward slash + .replace(/\\/g, '\\\\') // Replace every \ with \\ and encodURI. Double backslash means the HTML template will be able to parse the string correctly. encodeURI so Caspar doesn't mangle the data. + ), + noAnimation: false + }, + display: 'program' } - } + }, + partialUpdate: !IsTargetingFull(this.engine) } - } - return { - fileName, - path: JoinAssetToNetworkPath( - config.studio.GraphicNetworkBasePath, - graphicFolder, - parsedCue.graphic.name, - config.studio.GraphicFileExtension - ), - mediaFlowIds: [config.studio.GraphicMediaFlowId], - ignoreMediaObjectStatus: config.studio.GraphicIgnoreStatus, - ignoreBlackFrames: true, - ignoreFreezeFrame: true, - timelineObjects: [ - literal({ - id: '', - enable: { - while: '1' - }, - priority: 100, - layer: IsTargetingWall(engine) ? SharedGraphicLLayer.GraphicLLayerWall : SharedGraphicLLayer.GraphicLLayerPilot, - metaData: { templateData, fileName }, - content: { - deviceType: TSR.DeviceType.CASPARCG, - type: TSR.TimelineContentTypeCasparCg.TEMPLATE, - templateType: 'html', - name: 'sport-overlay/index', - data: templateData, - useStopCommand: false, - mixer: { - opacity: 100 + return { + fileName, + path: joinAssetToNetworkPath( + this.config.studio.GraphicNetworkBasePath, + graphicFolder, + sceneName, + this.config.studio.GraphicFileExtension + ), + mediaFlowIds: [this.config.studio.GraphicMediaFlowId], + ignoreMediaObjectStatus: this.config.studio.GraphicIgnoreStatus, + ignoreBlackFrames: true, + ignoreFreezeFrame: true, + timelineObjects: [ + literal({ + id: '', + enable: { + while: '1' + }, + priority: 100, + layer: this.layerMappingName, + metaData: { templateData, fileName }, + content: { + deviceType: TSR.DeviceType.CASPARCG, + type: TSR.TimelineContentTypeCasparCg.TEMPLATE, + templateType: 'html', + name: getHtmlTemplateName(this.config), + data: templateData, + useStopCommand: false, + mixer: { + opacity: 100 + } } - } - }), - ...(IsTargetingFull(engine) ? settings.createPilotTimelineForStudio(config, context) : []) - ] + }), + ...(IsTargetingFull(this.engine) + ? this.settings.caspar.createFullPilotTimelineForStudio(this.config) + : EnableDSK(this.config, 'OVL')) + ] + } + } + + private getSceneName() { + const nameChunks = this.parsedCue.graphic.name.split('/') + return nameChunks[nameChunks.length - 1] } } @@ -107,14 +116,12 @@ function CasparOverlayTimeline( config: TV2BlueprintConfig, engine: GraphicEngine, parsedCue: CueDefinitionGraphic, - partDefinition: PartDefinition | undefined, - mappedTemplate: string, - adlib: boolean + mappedTemplate: string ): TSR.TSRTimelineObj[] { return [ literal({ id: '', - enable: GetEnableForGraphic(config, engine, parsedCue, partDefinition, adlib), + enable: GetEnableForGraphic(config, engine, parsedCue), priority: 1, layer: GetTimelineLayerForGraphic(config, mappedTemplate), content: CreateHTMLRendererContent(config, mappedTemplate, { ...parsedCue.graphic.textFields }) @@ -133,10 +140,10 @@ export function CreateHTMLRendererContent( deviceType: TSR.DeviceType.CASPARCG, type: TSR.TimelineContentTypeCasparCg.TEMPLATE, templateType: 'html', - name: 'sport-overlay/index', + name: getHtmlTemplateName(config), data: { display: 'program', - slots: HTMLTemplateContent(config, mappedTemplate, data), + slots: getHtmlTemplateContent(config, mappedTemplate, data), partialUpdate: true }, useStopCommand: false, @@ -146,7 +153,7 @@ export function CreateHTMLRendererContent( } } -function HTMLTemplateContent(config: TV2BlueprintConfig, graphicTemplate: string, data: object): Partial { +function getHtmlTemplateContent(config: TV2BlueprintConfig, graphicTemplate: string, data: object): Partial { const layer = GetTimelineLayerForGraphic(config, graphicTemplate) const slot = layerToHTMLGraphicSlot[layer] @@ -165,3 +172,143 @@ function HTMLTemplateContent(config: TV2BlueprintConfig, graphicTemplate: string } } } + +export function getHtmlGraphicBaseline(config: TV2BlueprintConfig) { + const templateName = getHtmlTemplateName(config) + const partiallyUpdatableLayerMappings = [ + SharedGraphicLLayer.GraphicLLayerOverlayIdent, + SharedGraphicLLayer.GraphicLLayerOverlayLower, + SharedGraphicLLayer.GraphicLLayerOverlayTema, + SharedGraphicLLayer.GraphicLLayerOverlayTopt, + SharedGraphicLLayer.GraphicLLayerOverlayPilot, + SharedGraphicLLayer.GraphicLLayerLocators + ] + return [ + ...getSlotBaselineTimelineObjects(templateName, partiallyUpdatableLayerMappings), + getCompoundSlotBaselineTimelineObject(templateName, partiallyUpdatableLayerMappings), + getDesignBaselineTimelineObject(templateName), + getFullPilotBaselineTimelineObject(templateName) + ] +} + +function getSlotBaselineTimelineObjects( + templateName: string, + layerMappings: SharedGraphicLLayer[] +): TSR.TSRTimelineObj[] { + return layerMappings + .filter(layer => layerToHTMLGraphicSlot[layer]) + .map(layer => ({ + id: '', + enable: { + while: '1' + }, + priority: 0, + layer, + content: { + deviceType: TSR.DeviceType.CASPARCG, + type: TSR.TimelineContentTypeCasparCg.TEMPLATE, + templateType: 'html', + name: templateName, + data: { + display: 'program', + slots: { + [layerToHTMLGraphicSlot[layer]]: { + payload: {}, + display: 'hidden' + } + }, + partialUpdate: true + }, + useStopCommand: false + } + })) +} + +function getCompoundSlotBaselineTimelineObject( + templateName: string, + layerMappings: SharedGraphicLLayer[] +): TSR.TimelineObjCCGTemplate { + const slots = layerMappings.reduce((obj: Record, layer) => { + if (layerToHTMLGraphicSlot[layer]) { + obj[layerToHTMLGraphicSlot[layer]] = { + payload: {}, + display: 'hidden' + } + } + return obj + }, {}) + return { + id: '', + enable: { + while: '1' + }, + priority: 0, + layer: SharedGraphicLLayer.GraphicLLayerOverlay, + content: { + deviceType: TSR.DeviceType.CASPARCG, + type: TSR.TimelineContentTypeCasparCg.TEMPLATE, + templateType: 'html', + name: templateName, + data: { + display: 'program', + slots, + partialUpdate: true + }, + useStopCommand: false + } + } +} + +function getDesignBaselineTimelineObject(templateName: string): TSR.TimelineObjCCGTemplate { + return { + id: '', + enable: { + while: '1' + }, + priority: 0, + layer: SharedGraphicLLayer.GraphicLLayerDesign, + content: { + deviceType: TSR.DeviceType.CASPARCG, + type: TSR.TimelineContentTypeCasparCg.TEMPLATE, + templateType: 'html', + name: templateName, + data: { + display: 'program', + design: '', + partialUpdate: true + }, + useStopCommand: false + } + } +} + +function getFullPilotBaselineTimelineObject(templateName: string): TSR.TimelineObjCCGTemplate { + return { + id: '', + enable: { + while: '1' + }, + priority: 0, + layer: SharedGraphicLLayer.GraphicLLayerPilot, + content: { + deviceType: TSR.DeviceType.CASPARCG, + type: TSR.TimelineContentTypeCasparCg.TEMPLATE, + templateType: 'html', + name: templateName, + data: { + display: 'program', + slots: { + [layerToHTMLGraphicSlot[SharedGraphicLLayer.GraphicLLayerPilot]]: { + payload: {}, + display: 'hidden' + } + } + }, + useStopCommand: false + } + } +} + +export function getHtmlTemplateName(config: TV2BlueprintConfig) { + return joinAssetToFolder(config.selectedGraphicsSetup.HtmlPackageFolder, 'index') +} diff --git a/src/tv2-common/helpers/graphics/caspar/slotMappings.ts b/src/tv2-common/helpers/graphics/caspar/slotMappings.ts index 4eeb8c0c9..35d8f267a 100644 --- a/src/tv2-common/helpers/graphics/caspar/slotMappings.ts +++ b/src/tv2-common/helpers/graphics/caspar/slotMappings.ts @@ -12,7 +12,7 @@ export const layerToHTMLGraphicSlot: { [slot: string]: string } = { [SharedGraphicLLayer.GraphicLLayerOverlayTema]: '', [SharedGraphicLLayer.GraphicLLayerOverlayTopt]: '660_topt', [SharedGraphicLLayer.GraphicLLayerPilot]: '250_full', - [SharedGraphicLLayer.GraphicLLayerPilotOverlay]: '250_full', + [SharedGraphicLLayer.GraphicLLayerOverlayPilot]: '260_overlay', [SharedGraphicLLayer.GraphicLLayerLocators]: '850_dve' } diff --git a/src/tv2-common/helpers/graphics/design/index.ts b/src/tv2-common/helpers/graphics/design/index.ts index 2ca0b22cc..dc84f9e85 100644 --- a/src/tv2-common/helpers/graphics/design/index.ts +++ b/src/tv2-common/helpers/graphics/design/index.ts @@ -7,8 +7,8 @@ import { PieceLifespan, TSR, WithTimeline -} from '@tv2media/blueprints-integration' -import { CalculateTime, CueDefinitionGraphicDesign, literal, TV2BlueprintConfig } from 'tv2-common' +} from 'blueprints-integration' +import { CalculateTime, CueDefinitionGraphicDesign, getHtmlTemplateName, literal, TV2BlueprintConfig } from 'tv2-common' import { SharedGraphicLLayer, SharedOutputLayers, SharedSourceLayers } from 'tv2-constants' export function EvaluateDesignBase( @@ -78,7 +78,7 @@ function designTimeline(config: TV2BlueprintConfig, parsedCue: CueDefinitionGrap deviceType: TSR.DeviceType.CASPARCG, type: TSR.TimelineContentTypeCasparCg.TEMPLATE, templateType: 'html', - name: 'sport-overlay/index', + name: getHtmlTemplateName(config), data: { display: 'program', design: parsedCue.design, @@ -100,7 +100,7 @@ function designTimeline(config: TV2BlueprintConfig, parsedCue: CueDefinitionGrap type: TSR.TimelineContentTypeVizMSE.ELEMENT_INTERNAL, templateName: parsedCue.design, templateData: [], - showId: config.selectedGraphicsSetup.OvlShowId + showId: config.selectedGraphicsSetup.OvlShowName ?? '' // @todo: improve types at the junction of HTML and Viz } }) ] diff --git a/src/tv2-common/helpers/graphics/index.ts b/src/tv2-common/helpers/graphics/index.ts index c44b89bf7..5e31ff826 100644 --- a/src/tv2-common/helpers/graphics/index.ts +++ b/src/tv2-common/helpers/graphics/index.ts @@ -1,16 +1,15 @@ -import { IBlueprintPart, TSR } from '@tv2media/blueprints-integration' -import { layerToHTMLGraphicSlot, literal, TV2BlueprintConfig } from 'tv2-common' -import { GraphicEngine, SharedGraphicLLayer } from 'tv2-constants' - +export * from './pilot' +export * from './pilot/create' +export * from './caspar' +export * from './viz' export * from './name' export * from './timing' export * from './target' export * from './layers' export * from './internal' -export * from './pilot' -export * from './caspar' -export * from './viz' export * from './design' +import { IBlueprintPart, TSR } from 'blueprints-integration' +import { getHtmlGraphicBaseline, TV2BlueprintConfig } from 'tv2-common' export function ApplyFullGraphicPropertiesToPart(config: TV2BlueprintConfig, part: IBlueprintPart) { const keepAliveDuration = @@ -32,137 +31,6 @@ export function CreateGraphicBaseline(config: TV2BlueprintConfig): TSR.TSRTimeli if (config.studio.GraphicsType === 'VIZ') { return [] } else { - const slotBaselineObjects: TSR.TSRTimelineObj[] = [] - ;[ - SharedGraphicLLayer.GraphicLLayerOverlayIdent, - SharedGraphicLLayer.GraphicLLayerOverlayLower, - SharedGraphicLLayer.GraphicLLayerOverlayTema, - SharedGraphicLLayer.GraphicLLayerOverlayTopt, - SharedGraphicLLayer.GraphicLLayerLocators - ].forEach(layer => { - if (layerToHTMLGraphicSlot[layer]) { - slotBaselineObjects.push( - literal({ - id: '', - enable: { - while: '1' - }, - priority: 0, - layer, - content: { - deviceType: TSR.DeviceType.CASPARCG, - type: TSR.TimelineContentTypeCasparCg.TEMPLATE, - templateType: 'html', - name: 'sport-overlay/index', - data: { - display: 'program', - slots: { - [layerToHTMLGraphicSlot[layer]]: { - payload: {}, - display: 'hidden' - } - }, - partialUpdate: true - }, - useStopCommand: false - } - }) - ) - } - }) - - return [ - ...slotBaselineObjects, - literal({ - id: '', - enable: { - while: '1' - }, - priority: 0, - layer: SharedGraphicLLayer.GraphicLLayerOverlay, - content: { - deviceType: TSR.DeviceType.CASPARCG, - type: TSR.TimelineContentTypeCasparCg.TEMPLATE, - templateType: 'html', - name: 'sport-overlay/index', - data: { - display: 'program', - slots: [ - SharedGraphicLLayer.GraphicLLayerOverlayIdent, - SharedGraphicLLayer.GraphicLLayerOverlayLower, - SharedGraphicLLayer.GraphicLLayerOverlayTema, - SharedGraphicLLayer.GraphicLLayerOverlayTopt, - SharedGraphicLLayer.GraphicLLayerLocators - ].reduce((obj: Record, layer) => { - if (layerToHTMLGraphicSlot[layer]) { - obj[layerToHTMLGraphicSlot[layer]] = { - payload: {}, - display: 'hidden' - } - } - return obj - }, {}), - partialUpdate: true - }, - useStopCommand: false - } - }), - literal({ - id: '', - enable: { - while: '1' - }, - priority: 0, - layer: SharedGraphicLLayer.GraphicLLayerDesign, - content: { - deviceType: TSR.DeviceType.CASPARCG, - type: TSR.TimelineContentTypeCasparCg.TEMPLATE, - templateType: 'html', - name: 'sport-overlay/index', - data: { - display: 'program', - design: '', - partialUpdate: true - }, - useStopCommand: false - } - }), - literal({ - id: '', - enable: { - while: '1' - }, - priority: 0, - layer: SharedGraphicLLayer.GraphicLLayerPilot, - content: { - deviceType: TSR.DeviceType.CASPARCG, - type: TSR.TimelineContentTypeCasparCg.TEMPLATE, - templateType: 'html', - name: 'sport-overlay/index', - data: { - display: 'program', - slots: { - [layerToHTMLGraphicSlot[SharedGraphicLLayer.GraphicLLayerPilot]]: { - payload: {}, - display: 'hidden' - } - } - }, - useStopCommand: false - } - }) - ] - } -} - -export function findShowId(config: TV2BlueprintConfig, engine: GraphicEngine): string { - const graphicsSetup = config.selectedGraphicsSetup - switch (engine) { - case 'FULL': - case 'WALL': - return graphicsSetup.FullShowId - case 'TLF': - case 'OVL': - return graphicsSetup.OvlShowId + return getHtmlGraphicBaseline(config) } } diff --git a/src/tv2-common/helpers/graphics/internal/index.ts b/src/tv2-common/helpers/graphics/internal/index.ts index a38bd8cf8..96f09685c 100644 --- a/src/tv2-common/helpers/graphics/internal/index.ts +++ b/src/tv2-common/helpers/graphics/internal/index.ts @@ -1,4 +1,4 @@ -import { IBlueprintAdLibPiece, IBlueprintPiece, IShowStyleUserContext } from '@tv2media/blueprints-integration' +import { IBlueprintAdLibPiece, IBlueprintPiece, IShowStyleUserContext } from 'blueprints-integration' import { Adlib, CueDefinitionGraphic, @@ -19,7 +19,7 @@ export function CreateInternalGraphic( partDefinition: PartDefinition, adlib?: Adlib ) { - const internalGraphic: InternalGraphic = new InternalGraphic(config, parsedCue, adlib, partId, partDefinition) + const internalGraphic: InternalGraphic = new InternalGraphic(config, context, parsedCue, partId, partDefinition) if (!internalGraphic.mappedTemplate || !internalGraphic.mappedTemplate.length) { context.notifyUserWarning(`No valid template found for ${parsedCue.graphic.template}`) diff --git a/src/tv2-common/helpers/graphics/pilot/create.ts b/src/tv2-common/helpers/graphics/pilot/create.ts new file mode 100644 index 000000000..84a7b692e --- /dev/null +++ b/src/tv2-common/helpers/graphics/pilot/create.ts @@ -0,0 +1,28 @@ +import { IBlueprintActionManifest, IBlueprintAdLibPiece, IBlueprintPiece } from 'blueprints-integration' +import { IsTargetingFull, IsTargetingOVL, PilotGraphicGenerator, PilotGraphicProps } from 'tv2-common' + +export function CreatePilotGraphic( + pieces: IBlueprintPiece[], + adlibPieces: IBlueprintAdLibPiece[], + actions: IBlueprintActionManifest[], + pilotGraphicProps: PilotGraphicProps +) { + const { context, adlib, parsedCue } = pilotGraphicProps + if (parsedCue.graphic.vcpid < 0) { + context.notifyUserWarning('No valid VCPID provided') + return + } + + const generator = PilotGraphicGenerator.createPilotGraphicGenerator(pilotGraphicProps) + + if (IsTargetingOVL(parsedCue.target) && adlib) { + adlibPieces.push(generator.createAdlibPiece()) + } else { + pieces.push(generator.createPiece()) + } + + if (IsTargetingFull(parsedCue.target)) { + actions.push(generator.createFullPilotAdLibAction()) + pieces.push(generator.createFullDataStore()) + } +} diff --git a/src/tv2-common/helpers/graphics/pilot/index.ts b/src/tv2-common/helpers/graphics/pilot/index.ts index 5308631c5..18a503b33 100644 --- a/src/tv2-common/helpers/graphics/pilot/index.ts +++ b/src/tv2-common/helpers/graphics/pilot/index.ts @@ -7,41 +7,42 @@ import { PieceLifespan, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionSelectFullGrafik, Adlib, + assertUnreachable, + CasparPilotGeneratorSettings, CreateTimingGraphic, CueDefinitionGraphic, FullPieceMetaData, generateExternalId, GetFullGraphicTemplateNameFromCue, GetPieceLifespanForGraphic, - GetPilotGraphicContentViz, GetTagForFull, GetTagForFullNext, GraphicDisplayName, GraphicPilot, + HtmlPilotGraphicGenerator, IsTargetingFull, - IsTargetingOVL, - IsTargetingTLF, IsTargetingWall, literal, PieceMetaData, SisyfosPersistMetaData, - TV2BlueprintConfig + t, + TV2BlueprintConfig, + VizPilotGeneratorSettings, + VizPilotGraphicGenerator } from 'tv2-common' import { AdlibActionType, AdlibTags, GraphicEngine, + SharedGraphicLLayer, SharedOutputLayers, SharedSourceLayers, TallyTags } from 'tv2-constants' -import { t } from '../../translation' -import { CasparPilotGeneratorSettings, GetPilotGraphicContentCaspar } from '../caspar' -import { VizPilotGeneratorSettings } from '../viz' // Work needed, this should be more generic than expecting showstyles to define how to display pilot graphics export interface PilotGeneratorSettings { @@ -52,7 +53,6 @@ export interface PilotGeneratorSettings { export interface PilotGraphicProps { config: TV2BlueprintConfig context: IShowStyleUserContext - engine: GraphicEngine partId: string parsedCue: CueDefinitionGraphic settings: PilotGeneratorSettings @@ -60,51 +60,26 @@ export interface PilotGraphicProps { segmentExternalId: string } -export function CreatePilotGraphic( - pieces: IBlueprintPiece[], - adlibPieces: IBlueprintAdLibPiece[], - actions: IBlueprintActionManifest[], - pilotGraphicProps: PilotGraphicProps -) { - const { context, engine, adlib, parsedCue } = pilotGraphicProps - if ( - parsedCue.graphic.vcpid === undefined || - parsedCue.graphic.vcpid === null || - parsedCue.graphic.vcpid.toString() === '' || - parsedCue.graphic.vcpid.toString().length === 0 - ) { - context.notifyUserWarning('No valid VCPID provided') - return - } - - const generator = new PilotGraphicGenerator(pilotGraphicProps) - - if (IsTargetingOVL(engine) && adlib) { - adlibPieces.push(generator.createAdlibPiece()) - } else { - pieces.push(generator.createPiece()) - } - - if (IsTargetingFull(engine)) { - actions.push(generator.createPilotAdLibAction()) - pieces.push(generator.createFullDataStore()) +export abstract class PilotGraphicGenerator { + public static createPilotGraphicGenerator(graphicProps: PilotGraphicProps): PilotGraphicGenerator { + if (graphicProps.config.studio.GraphicsType === 'HTML') { + return new HtmlPilotGraphicGenerator(graphicProps) + } + return new VizPilotGraphicGenerator(graphicProps) } -} - -export class PilotGraphicGenerator { - private readonly config: TV2BlueprintConfig - private readonly context: IShowStyleUserContext - private readonly engine: GraphicEngine - private readonly partId: string - private readonly parsedCue: CueDefinitionGraphic - private readonly settings: PilotGeneratorSettings - private readonly adlib?: Adlib - private readonly segmentExternalId: string - - constructor(graphicProps: PilotGraphicProps) { + protected readonly config: TV2BlueprintConfig + protected readonly context: IShowStyleUserContext + protected readonly engine: GraphicEngine + protected readonly partId: string + protected readonly parsedCue: CueDefinitionGraphic + protected readonly settings: PilotGeneratorSettings + protected readonly adlib?: Adlib + protected readonly segmentExternalId: string + + protected constructor(graphicProps: PilotGraphicProps) { this.config = graphicProps.config this.context = graphicProps.context - this.engine = graphicProps.engine + this.engine = graphicProps.parsedCue.target this.parsedCue = graphicProps.parsedCue this.partId = graphicProps.partId this.settings = graphicProps.settings @@ -112,7 +87,9 @@ export class PilotGraphicGenerator { this.segmentExternalId = graphicProps.segmentExternalId } - public createPilotAdLibAction(): IBlueprintActionManifest { + public abstract getContent(): WithTimeline + + public createFullPilotAdLibAction(): IBlueprintActionManifest { const name = GraphicDisplayName(this.config, this.parsedCue) const sourceLayerId = this.getSourceLayer() const outputLayerId = this.getOutputLayer() @@ -133,7 +110,7 @@ export class PilotGraphicGenerator { label: t(GetFullGraphicTemplateNameFromCue(this.config, this.parsedCue)), sourceLayerId: SharedSourceLayers.PgmPilot, outputLayerId: SharedOutputLayers.PGM, - content: this.createContent(), + content: this.getContent(), uniquenessId: `gfx_${name}_${sourceLayerId}_${outputLayerId}`, tags: [ AdlibTags.ADLIB_KOMMENTATOR, @@ -167,7 +144,7 @@ export class PilotGraphicGenerator { sisyfosLayers: [] } }, - content: this.createContent(), + content: this.getContent(), tags: IsTargetingFull(this.engine) ? [GetTagForFull(this.segmentExternalId, this.parsedCue.graphic.vcpid), TallyTags.FULL_IS_LIVE] : [] @@ -176,7 +153,7 @@ export class PilotGraphicGenerator { public createAdlibPiece(rank?: number): IBlueprintAdLibPiece { const pilotPiece = this.createPiece() - pilotPiece.tags = [...(pilotPiece.tags ?? []), AdlibTags.ADLIB_FLOW_PRODUCER] + pilotPiece.tags = [...(pilotPiece.tags ?? []), AdlibTags.ADLIB_FLOW_PRODUCER, AdlibTags.ADLIB_KOMMENTATOR] return { ...pilotPiece, _rank: rank ?? 0 @@ -184,7 +161,7 @@ export class PilotGraphicGenerator { } public createFullDataStore(): IBlueprintPiece { - const content = this.createContent() + const content = this.getContent() content.timelineObjects = content.timelineObjects.filter( o => o.content.deviceType !== TSR.DeviceType.ATEM && @@ -217,46 +194,52 @@ export class PilotGraphicGenerator { } } - private createContent(): WithTimeline { - if (this.config.studio.GraphicsType === 'HTML') { - return GetPilotGraphicContentCaspar(this.config, this.context, this.parsedCue, this.settings.caspar, this.engine) - } else { - return GetPilotGraphicContentViz( - this.config, - this.context, - this.settings.viz, - this.parsedCue, - this.engine, - this.adlib - ) - } - } - - private getPrerollDuration(): number { + protected getPrerollDuration(): number { return this.config.studio.GraphicsType === 'HTML' ? this.config.studio.CasparPrerollDuration : this.config.studio.VizPilotGraphics.PrerollDuration } - private getSourceLayer(): SharedSourceLayers { - const engine = this.engine - return IsTargetingWall(engine) - ? SharedSourceLayers.WallGraphics - : IsTargetingTLF(engine) - ? SharedSourceLayers.PgmGraphicsTLF - : IsTargetingOVL(engine) - ? SharedSourceLayers.PgmPilotOverlay - : SharedSourceLayers.PgmPilot + protected getSourceLayer(): SharedSourceLayers { + switch (this.engine) { + case 'WALL': + return SharedSourceLayers.WallGraphics + case 'TLF': + return SharedSourceLayers.PgmGraphicsTLF + case 'OVL': + return SharedSourceLayers.PgmPilotOverlay + case 'FULL': + return SharedSourceLayers.PgmPilot + default: + assertUnreachable(this.engine) + } } - private getOutputLayer() { - const engine = this.engine - return IsTargetingWall(engine) - ? SharedOutputLayers.SEC - : IsTargetingOVL(engine) - ? SharedOutputLayers.OVERLAY - : IsTargetingFull(engine) - ? SharedOutputLayers.PGM - : SharedOutputLayers.OVERLAY + protected getOutputLayer(): SharedOutputLayers { + switch (this.engine) { + case 'WALL': + return SharedOutputLayers.SEC + case 'OVL': + return SharedOutputLayers.OVERLAY + case 'FULL': + case 'TLF': + return SharedOutputLayers.PGM + default: + assertUnreachable(this.engine) + } + } + + protected getLayerMappingName(): SharedGraphicLLayer { + switch (this.engine) { + case 'WALL': + return SharedGraphicLLayer.GraphicLLayerWall + case 'OVL': + return SharedGraphicLLayer.GraphicLLayerOverlayPilot + case 'FULL': + case 'TLF': + return SharedGraphicLLayer.GraphicLLayerPilot + default: + assertUnreachable(this.engine) + } } } diff --git a/src/tv2-common/helpers/graphics/timing.ts b/src/tv2-common/helpers/graphics/timing.ts index 3bfd74a9a..2df2ba6f3 100644 --- a/src/tv2-common/helpers/graphics/timing.ts +++ b/src/tv2-common/helpers/graphics/timing.ts @@ -1,4 +1,4 @@ -import { PieceLifespan, TSR } from '@tv2media/blueprints-integration' +import { PieceLifespan, TSR } from 'blueprints-integration' import { CalculateTime, CreateTimingEnable, @@ -8,9 +8,7 @@ import { GraphicIsInternal, GraphicIsPilot, LifeSpan, - PartDefinition, - PartToParentClass, - TableConfigItemGFXTemplates, + TableConfigItemGfxTemplate, TV2BlueprintConfig } from 'tv2-common' import { GraphicEngine } from 'tv2-constants' @@ -27,8 +25,11 @@ export function GetPieceLifespanForGraphic( if (IsTargetingTLF(engine)) { return PieceLifespan.WithinPart } - if (parsedCue.end && parsedCue.end.infiniteMode) { - return LifeSpan(parsedCue.end.infiniteMode, PieceLifespan.WithinPart) + if (parsedCue.end?.infiniteMode) { + return LifeSpan(parsedCue.end.infiniteMode) + } + if (parsedCue.end && CalculateTime(parsedCue.end)) { + return PieceLifespan.WithinPart } return FindInfiniteModeFromConfig(config, parsedCue) } @@ -60,7 +61,7 @@ export function FindInfiniteModeFromConfig( return PieceLifespan.WithinPart } - return LifeSpan(type, PieceLifespan.WithinPart) + return LifeSpan(type) } export function GetGraphicDuration( @@ -68,7 +69,7 @@ export function GetGraphicDuration( cue: CueDefinitionGraphic ): number | undefined { if (config.showStyle.GFXTemplates) { - const template = findGFXTemplate(config, cue) + const template = findGfxTemplate(config, cue) if (template && template.OutType && !template.OutType.toString().match(/default/i)) { return undefined } @@ -104,10 +105,10 @@ export function GetEnableForWall(): TSR.TSRTimelineObj['enable'] { } } -export function findGFXTemplate( +export function findGfxTemplate( config: TV2BlueprintConfig, cue: CueDefinitionGraphic -): TableConfigItemGFXTemplates | undefined { +): TableConfigItemGfxTemplate | undefined { let graphicId: string | undefined if (GraphicIsInternal(cue)) { graphicId = cue.graphic.template @@ -124,22 +125,12 @@ export function findGFXTemplate( export function GetEnableForGraphic( config: TV2BlueprintConfig, engine: GraphicEngine, - cue: CueDefinitionGraphic, - partDefinition?: PartDefinition, - adlib?: boolean + cue: CueDefinitionGraphic ): TSR.TSRTimelineObj['enable'] { if (IsTargetingWall(engine)) { return GetEnableForWall() } - if ( - partDefinition && - (endsOnPartEnd(config, cue) || GetPieceLifespanForGraphic(engine, config, cue) === PieceLifespan.OutOnSegmentEnd) && - !adlib - ) { - return { while: `.${PartToParentClass('studio0', partDefinition)} & !.adlib_deparent & !.full` } - } - const timing = CreateTimingEnable(cue, GetDefaultOut(config)) if (!timing.lifespan) { @@ -156,8 +147,3 @@ 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 973f952ac..d01a27027 100644 --- a/src/tv2-common/helpers/graphics/viz/index.ts +++ b/src/tv2-common/helpers/graphics/viz/index.ts @@ -1,38 +1,97 @@ -import { GraphicsContent, IShowStyleUserContext, TSR, WithTimeline } from '@tv2media/blueprints-integration' +import { GraphicsContent, IShowStyleUserContext, TSR, WithTimeline } from 'blueprints-integration' import { - Adlib, + assertUnreachable, CueDefinitionGraphic, - findShowId, GetEnableForGraphic, GetFullGraphicTemplateNameFromCue, GetTimelineLayerForGraphic, GraphicInternal, - GraphicPilot, IsTargetingFull, IsTargetingOVL, IsTargetingWall, literal, - PartDefinition, + PilotGraphicProps, TV2BlueprintConfig } from 'tv2-common' -import { GraphicEngine, SharedGraphicLLayer } from 'tv2-constants' +import { GraphicEngine } from 'tv2-constants' import { EnableDSK } from '../../dsk' +import { PilotGraphicGenerator } from '../pilot/index' + +export class VizPilotGraphicGenerator extends PilotGraphicGenerator { + constructor(graphicProps: PilotGraphicProps) { + super(graphicProps) + } + public getContent(): WithTimeline { + return { + fileName: 'PILOT_' + this.parsedCue.graphic.vcpid.toString(), + path: this.parsedCue.graphic.vcpid.toString(), + timelineObjects: [ + literal({ + id: '', + enable: this.getEnable(), + priority: 1, + layer: this.getLayerMappingName(), + content: { + deviceType: TSR.DeviceType.VIZMSE, + type: TSR.TimelineContentTypeVizMSE.ELEMENT_PILOT, + templateVcpId: this.parsedCue.graphic.vcpid, + continueStep: this.parsedCue.graphic.continueCount, + noAutoPreloading: false, + channelName: this.getChannelName(), + ...this.getOutTransitionProperties() + }, + ...(IsTargetingFull(this.engine) ? { classes: ['full'] } : {}) + }), + ...(IsTargetingFull(this.engine) ? this.settings.viz.createFullPilotTimelineForStudio(this.config) : []) + ] + } + } + + private getEnable() { + if (IsTargetingOVL(this.engine) || IsTargetingWall(this.engine)) { + return GetEnableForGraphic(this.config, this.engine, this.parsedCue) + } + return { start: 0 } + } + + private getChannelName() { + switch (this.engine) { + case 'WALL': + return 'WALL1' + case 'OVL': + return 'OVL1' + case 'FULL': + case 'TLF': + return 'FULL1' + default: + assertUnreachable(this.engine) + } + } + + private getOutTransitionProperties(): Partial { + if (IsTargetingWall(this.engine) || !this.config.studio.PreventOverlayWithFull) { + return {} + } + return { + delayTakeAfterOutTransition: true, + outTransition: { + type: TSR.VIZMSETransitionType.DELAY, + delay: this.config.studio.VizPilotGraphics.OutTransitionDuration + } + } + } +} export interface VizPilotGeneratorSettings { - createPilotTimelineForStudio( - config: TV2BlueprintConfig, - context: IShowStyleUserContext, - adlib: boolean - ): TSR.TSRTimelineObj[] + createFullPilotTimelineForStudio(config: TV2BlueprintConfig): TSR.TSRTimelineObj[] } export function GetInternalGraphicContentVIZ( config: TV2BlueprintConfig, + context: IShowStyleUserContext, engine: GraphicEngine, parsedCue: CueDefinitionGraphic, - partDefinition: PartDefinition | undefined, - mappedTemplate: string, - adlib: boolean + mappedTemplate: string ): WithTimeline { return { fileName: parsedCue.graphic.template, @@ -41,7 +100,7 @@ export function GetInternalGraphicContentVIZ( timelineObjects: literal([ literal({ id: '', - enable: GetEnableForGraphic(config, engine, parsedCue, partDefinition, adlib), + enable: GetEnableForGraphic(config, engine, parsedCue), priority: 1, layer: GetTimelineLayerForGraphic(config, GetFullGraphicTemplateNameFromCue(config, parsedCue)), content: { @@ -50,7 +109,7 @@ export function GetInternalGraphicContentVIZ( templateName: mappedTemplate, templateData: parsedCue.graphic.textFields, channelName: engine === 'WALL' ? 'WALL1' : 'OVL1', // TODO: TranslateEngine - showId: findShowId(config, engine) + showId: findShowName(config, context, engine) } }), // Assume DSK is off by default (config table) @@ -59,52 +118,22 @@ export function GetInternalGraphicContentVIZ( } } -export function GetPilotGraphicContentViz( - config: TV2BlueprintConfig, - context: IShowStyleUserContext, - settings: VizPilotGeneratorSettings, - parsedCue: CueDefinitionGraphic, - engine: GraphicEngine, - adlib?: Adlib -): WithTimeline { - return { - fileName: 'PILOT_' + parsedCue.graphic.vcpid.toString(), - path: parsedCue.graphic.vcpid.toString(), - timelineObjects: [ - literal({ - id: '', - enable: - IsTargetingOVL(engine) || IsTargetingWall(engine) - ? GetEnableForGraphic(config, engine, parsedCue, undefined, !!adlib) - : { - start: 0 - }, - priority: 1, - layer: IsTargetingWall(engine) - ? SharedGraphicLLayer.GraphicLLayerWall - : IsTargetingOVL(engine) - ? SharedGraphicLLayer.GraphicLLayerPilotOverlay - : SharedGraphicLLayer.GraphicLLayerPilot, - content: { - deviceType: TSR.DeviceType.VIZMSE, - type: TSR.TimelineContentTypeVizMSE.ELEMENT_PILOT, - templateVcpId: parsedCue.graphic.vcpid, - continueStep: parsedCue.graphic.continueCount, - noAutoPreloading: false, - channelName: engine === 'WALL' ? 'WALL1' : engine === 'OVL' ? 'OVL1' : 'FULL1', // TODO: TranslateEngine - ...(IsTargetingWall(engine) || !config.studio.PreventOverlayWithFull - ? {} - : { - delayTakeAfterOutTransition: true, - outTransition: { - type: TSR.VIZMSETransitionType.DELAY, - delay: config.studio.VizPilotGraphics.OutTransitionDuration - } - }) - }, - ...(IsTargetingFull(engine) ? { classes: ['full'] } : {}) - }), - ...(IsTargetingFull(engine) ? settings.createPilotTimelineForStudio(config, context, !!adlib) : []) - ] +function findShowName(config: TV2BlueprintConfig, context: IShowStyleUserContext, engine: GraphicEngine): string { + const graphicsSetup = config.selectedGraphicsSetup + switch (engine) { + case 'FULL': + case 'WALL': + if (graphicsSetup.FullShowName === undefined) { + context.logWarning("You're using Viz graphics with an incompatible ShowStyle") + return '' + } + return graphicsSetup.FullShowName + case 'TLF': + case 'OVL': + if (graphicsSetup.OvlShowName === undefined) { + context.logWarning("You're using Viz graphics with an incompatible ShowStyle") + return '' + } + return graphicsSetup.OvlShowName } } diff --git a/src/tv2-common/helpers/rundownAdLibActions.ts b/src/tv2-common/helpers/rundownAdLibActions.ts index 05402989d..0558625c9 100644 --- a/src/tv2-common/helpers/rundownAdLibActions.ts +++ b/src/tv2-common/helpers/rundownAdLibActions.ts @@ -1,4 +1,4 @@ -import { IBlueprintActionManifest } from '@tv2media/blueprints-integration' +import { IBlueprintActionManifest } from 'blueprints-integration' import { ActionTakeWithTransition, ActionTakeWithTransitionVariant, @@ -16,6 +16,15 @@ import { TV2BlueprintConfig } from '../blueprintConfig' import { CreateJingleExpectedMedia } from '../content' import { t } from './translation' +interface TransitionValues { + rank: number + label: string + jingle: string + alphaAtStart?: number + duration?: number + alphaAtEnd?: number +} + export function GetTransitionAdLibActions< StudioConfig extends TV2StudioConfigBase, ShowStyleConfig extends TV2BlueprintConfigBase @@ -23,82 +32,48 @@ export function GetTransitionAdLibActions< const blueprintActionManifests: IBlueprintActionManifest[] = [] if (config.showStyle.ShowstyleTransition && config.showStyle.ShowstyleTransition.length) { - const defaultTransition = config.showStyle.ShowstyleTransition - - 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 - ) - let alphaAtStart: number | undefined - let duration: number | undefined - let alphaAtEnd: number | undefined - - if (jingleConfig) { - alphaAtStart = jingleConfig.StartAlpha - duration = jingleConfig.Duration - alphaAtEnd = jingleConfig.EndAlpha - } - blueprintActionManifests.push( - makeTransitionAction( - config, - userData, - startingRank, - config.showStyle.ShowstyleTransition, - jingleConfig?.ClipName ?? config.showStyle.ShowstyleTransition, - alphaAtStart, - duration, - alphaAtEnd - ) + ...createActionsForTransition(config, config.showStyle.ShowstyleTransition, startingRank) ) } startingRank++ if (config.showStyle.Transitions) { - config.showStyle.Transitions.forEach((transition, i) => { - if (transition.Transition && transition.Transition.length) { - 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 - let duration: number | undefined - let alphaAtEnd: number | undefined - - if (jingleConfig) { - alphaAtStart = jingleConfig.StartAlpha - duration = jingleConfig.Duration - alphaAtEnd = jingleConfig.EndAlpha - } - - blueprintActionManifests.push( - makeTransitionAction( - config, - userData, - startingRank + 0.01 * i, - transition.Transition, - jingleConfig?.ClipName ?? transition.Transition, - alphaAtStart, - duration, - alphaAtEnd - ) - ) - } - }) + const transitionActions: IBlueprintActionManifest[] = config.showStyle.Transitions.filter( + transition => transition.Transition && transition.Transition.length + ).flatMap((transition, i) => createActionsForTransition(config, transition.Transition, startingRank + 0.01 * i)) + blueprintActionManifests.push(...transitionActions) } return blueprintActionManifests } +function createActionsForTransition( + config: TV2BlueprintConfig, + transition: string, + rank: number +): IBlueprintActionManifest[] { + const jingleConfig = config.showStyle.BreakerConfig.find(j => j.BreakerName === transition) + const transitionValues: TransitionValues = { + rank, + label: transition, + jingle: jingleConfig?.ClipName ?? transition + } + + if (jingleConfig) { + transitionValues.alphaAtStart = jingleConfig.StartAlpha + transitionValues.duration = jingleConfig.Duration + transitionValues.alphaAtEnd = jingleConfig.EndAlpha + } + + const variant: ActionTakeWithTransitionVariant = ParseTransitionString(transition) + return [ + makeTransitionOnTakeAction(config, variant, transitionValues), + makeTransitionOnNextTakeAction(config, variant, transitionValues) + ] +} + export function ParseTransitionString(transitionString: string): ActionTakeWithTransitionVariant { if (transitionString.match(/mix ?(\d+)/i)) { const props = transitionString.match(/mix ?(\d+)/i) @@ -128,36 +103,66 @@ export function ParseTransitionString(transitionString: string): ActionTakeWithT }) } +function makeTransitionOnTakeAction( + config: TV2BlueprintConfig, + variant: ActionTakeWithTransitionVariant, + transitionValues: TransitionValues +): IBlueprintActionManifest { + const userData: ActionTakeWithTransition = { + type: AdlibActionType.TAKE_WITH_TRANSITION, + variant, + takeNow: true + } + return makeTransitionAction(config, userData, transitionValues, AdlibTags.ADLIB_TAKE_WITH_TRANSITION) +} + +function makeTransitionOnNextTakeAction( + config: TV2BlueprintConfig, + variant: ActionTakeWithTransitionVariant, + transitionValues: TransitionValues +): IBlueprintActionManifest { + const userData: ActionTakeWithTransition = { + type: AdlibActionType.TAKE_WITH_TRANSITION, + variant, + takeNow: false + } + return makeTransitionAction(config, userData, transitionValues, AdlibTags.ADLIB_NEXT_TAKE_WITH_TRANSITION) +} + function makeTransitionAction( config: TV2BlueprintConfig, userData: ActionTakeWithTransition, - rank: number, - label: string, - jingle: string, - alphaAtStart: number | undefined, - duration: number | undefined, - alphaAtEnd: number | undefined + transitionValues: TransitionValues, + adlibTag: AdlibTags ): IBlueprintActionManifest { const tag = GetTagForTransition(userData.variant) - const isEffekt = !!label.match(/^\d+$/) + const isEffekt = /^\d+$/.test(transitionValues.label) return { - externalId: `${JSON.stringify(userData)}_${AdlibActionType.TAKE_WITH_TRANSITION}_${rank}`, + externalId: `${JSON.stringify(userData)}_${AdlibActionType.TAKE_WITH_TRANSITION}_${transitionValues.rank}`, actionId: AdlibActionType.TAKE_WITH_TRANSITION, userData, userDataManifest: {}, display: { - _rank: rank, - label: t(isEffekt ? `EFFEKT ${label}` : label), + _rank: transitionValues.rank, + label: t(`${isEffekt ? 'EFFEKT ' : ''}${transitionValues.label}`), sourceLayerId: SharedSourceLayers.PgmAdlibJingle, outputLayerId: SharedOutputLayers.PGM, - tags: [AdlibTags.ADLIB_STATIC_BUTTON, AdlibTags.ADLIB_TAKE_WITH_TRANSITION], + tags: [AdlibTags.ADLIB_STATIC_BUTTON, adlibTag], currentPieceTags: [tag], nextPieceTags: [tag], content: - isEffekt || !!/^MIX ?\d+$/i.test(label) || !!/^CUT$/i.test(label) || !!/^DIP ?\d+$/i.test(label) + /^MIX ?\d+$/i.test(transitionValues.label) || + /^CUT$/i.test(transitionValues.label) || + /^DIP ?\d+$/i.test(transitionValues.label) ? {} - : CreateJingleExpectedMedia(config, jingle, alphaAtStart ?? 0, duration ?? 0, alphaAtEnd ?? 0) + : CreateJingleExpectedMedia( + config, + transitionValues.jingle, + transitionValues.alphaAtStart ?? 0, + transitionValues.duration ?? 0, + transitionValues.alphaAtEnd ?? 0 + ) } } } diff --git a/src/tv2-common/helpers/serverResume.ts b/src/tv2-common/helpers/serverResume.ts index 28d6bb96b..741577192 100644 --- a/src/tv2-common/helpers/serverResume.ts +++ b/src/tv2-common/helpers/serverResume.ts @@ -4,7 +4,7 @@ import { IBlueprintPartInstance, IBlueprintResolvedPieceInstance, VTContent -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { PartEndStateExt, PieceMetaData, t } from 'tv2-common' import { SharedSourceLayers } from 'tv2-constants' import _ = require('underscore') diff --git a/src/tv2-common/helpers/sisyfos.ts b/src/tv2-common/helpers/sisyfos.ts index 01f382fdd..a1df4abee 100644 --- a/src/tv2-common/helpers/sisyfos.ts +++ b/src/tv2-common/helpers/sisyfos.ts @@ -1,4 +1,4 @@ -import { Timeline, TSR } from '@tv2media/blueprints-integration' +import { Timeline, TSR } from 'blueprints-integration' import { SourceInfo, TimelineBlueprintExt } from 'tv2-common' import { SharedSisyfosLLayer } from 'tv2-constants' import { TV2BlueprintConfig } from '../blueprintConfig' diff --git a/src/tv2-common/helpers/translation.ts b/src/tv2-common/helpers/translation.ts index c1ac374d8..3f39fa354 100644 --- a/src/tv2-common/helpers/translation.ts +++ b/src/tv2-common/helpers/translation.ts @@ -1,4 +1,4 @@ -import { ITranslatableMessage } from '@tv2media/blueprints-integration' +import { ITranslatableMessage } from 'blueprints-integration' export function t(key: string, args?: { [k: string]: any }): ITranslatableMessage { return { diff --git a/src/tv2-common/hotkeys/camera.ts b/src/tv2-common/hotkeys/camera.ts index 94139e9b0..e4d4b468f 100644 --- a/src/tv2-common/hotkeys/camera.ts +++ b/src/tv2-common/hotkeys/camera.ts @@ -1,4 +1,4 @@ -import { IBlueprintTriggeredActions } from '@tv2media/blueprints-integration' +import { IBlueprintTriggeredActions } from 'blueprints-integration' import { MakeStudioSourceHotkeys, SourceHotkeyTriggers } from './helpers' export type CameraHotkeyAssignments = SourceHotkeyTriggers diff --git a/src/tv2-common/hotkeys/clear.ts b/src/tv2-common/hotkeys/clear.ts index 0451c7a42..b8e33f540 100644 --- a/src/tv2-common/hotkeys/clear.ts +++ b/src/tv2-common/hotkeys/clear.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' export type ClearLayerHotkeyAssignments = Array<{ sourceLayers: string[]; key: string; name: string }> diff --git a/src/tv2-common/hotkeys/dve.ts b/src/tv2-common/hotkeys/dve.ts index 0e8e4f3ba..7b7682d4a 100644 --- a/src/tv2-common/hotkeys/dve.ts +++ b/src/tv2-common/hotkeys/dve.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' import { AdlibTags } from 'tv2-constants' diff --git a/src/tv2-common/hotkeys/global.ts b/src/tv2-common/hotkeys/global.ts index 9b2af643a..8a9e2bb78 100644 --- a/src/tv2-common/hotkeys/global.ts +++ b/src/tv2-common/hotkeys/global.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' import { AdlibTags, SharedSourceLayers } from 'tv2-constants' import { CameraHotkeyAssignments, MakeCameraHotkeys } from './camera' diff --git a/src/tv2-common/hotkeys/graphics.ts b/src/tv2-common/hotkeys/graphics.ts index 1c28e1d75..b8591272d 100644 --- a/src/tv2-common/hotkeys/graphics.ts +++ b/src/tv2-common/hotkeys/graphics.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' import { AdlibTags } from 'tv2-constants' diff --git a/src/tv2-common/hotkeys/helpers/auxGraphics.ts b/src/tv2-common/hotkeys/helpers/auxGraphics.ts index 18e20427c..1246c592f 100644 --- a/src/tv2-common/hotkeys/helpers/auxGraphics.ts +++ b/src/tv2-common/hotkeys/helpers/auxGraphics.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' import { AdlibTags } from 'tv2-constants' diff --git a/src/tv2-common/hotkeys/helpers/auxStudioScreen.ts b/src/tv2-common/hotkeys/helpers/auxStudioScreen.ts index 6fa970b58..deff96af9 100644 --- a/src/tv2-common/hotkeys/helpers/auxStudioScreen.ts +++ b/src/tv2-common/hotkeys/helpers/auxStudioScreen.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' import { AdlibTags } from 'tv2-constants' diff --git a/src/tv2-common/hotkeys/helpers/cutToBox.ts b/src/tv2-common/hotkeys/helpers/cutToBox.ts index 5530dfef7..894db2883 100644 --- a/src/tv2-common/hotkeys/helpers/cutToBox.ts +++ b/src/tv2-common/hotkeys/helpers/cutToBox.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' import { AdlibTagCutToBox } from 'tv2-constants' diff --git a/src/tv2-common/hotkeys/helpers/directCut.ts b/src/tv2-common/hotkeys/helpers/directCut.ts index 25a251471..2199b7de9 100644 --- a/src/tv2-common/hotkeys/helpers/directCut.ts +++ b/src/tv2-common/hotkeys/helpers/directCut.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' import { AdlibTags } from 'tv2-constants' diff --git a/src/tv2-common/hotkeys/helpers/queue.ts b/src/tv2-common/hotkeys/helpers/queue.ts index c65e28bf1..af567a8ce 100644 --- a/src/tv2-common/hotkeys/helpers/queue.ts +++ b/src/tv2-common/hotkeys/helpers/queue.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' import { AdlibTags } from 'tv2-constants' diff --git a/src/tv2-common/hotkeys/helpers/studioSource.ts b/src/tv2-common/hotkeys/helpers/studioSource.ts index 1298bf4ff..d609241d2 100644 --- a/src/tv2-common/hotkeys/helpers/studioSource.ts +++ b/src/tv2-common/hotkeys/helpers/studioSource.ts @@ -1,4 +1,4 @@ -import { IBlueprintTriggeredActions } from '@tv2media/blueprints-integration' +import { IBlueprintTriggeredActions } from 'blueprints-integration' import { MakeRouteToGraphicsEngineTrigger } from './auxGraphics' import { MakeRouteToStudioScreenTrigger } from './auxStudioScreen' import { MakeCutToBoxTrigger } from './cutToBox' diff --git a/src/tv2-common/hotkeys/index.ts b/src/tv2-common/hotkeys/index.ts index 572d5cd29..279d725df 100644 --- a/src/tv2-common/hotkeys/index.ts +++ b/src/tv2-common/hotkeys/index.ts @@ -1,4 +1,4 @@ -import { ISourceLayer } from '@tv2media/blueprints-integration' +import { ISourceLayer } from 'blueprints-integration' import { GlobalHotkeySourceLayers, GlobalHotkeySources, diff --git a/src/tv2-common/hotkeys/local.ts b/src/tv2-common/hotkeys/local.ts index 48e0e507c..71cd8462a 100644 --- a/src/tv2-common/hotkeys/local.ts +++ b/src/tv2-common/hotkeys/local.ts @@ -1,4 +1,4 @@ -import { IBlueprintTriggeredActions } from '@tv2media/blueprints-integration' +import { IBlueprintTriggeredActions } from 'blueprints-integration' import { AdlibTags } from 'tv2-constants' import { replaySourceFullAudioName, replaySourceVoAudioName } from '../helpers' import { MakeStudioSourceHotkeys, SourceHotkeyTriggers } from './helpers' diff --git a/src/tv2-common/hotkeys/remote.ts b/src/tv2-common/hotkeys/remote.ts index 752cf6a28..36fafab87 100644 --- a/src/tv2-common/hotkeys/remote.ts +++ b/src/tv2-common/hotkeys/remote.ts @@ -1,4 +1,4 @@ -import { IBlueprintTriggeredActions } from '@tv2media/blueprints-integration' +import { IBlueprintTriggeredActions } from 'blueprints-integration' import { MakeStudioSourceHotkeys, SourceHotkeyTriggers } from './helpers' export type RemoteSourceHotkeyAssignments = SourceHotkeyTriggers diff --git a/src/tv2-common/hotkeys/rundownView.ts b/src/tv2-common/hotkeys/rundownView.ts index 406fb943a..341f5c44e 100644 --- a/src/tv2-common/hotkeys/rundownView.ts +++ b/src/tv2-common/hotkeys/rundownView.ts @@ -7,7 +7,7 @@ import { PlayoutActions, SomeAction, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' export interface RundownViewHotkeyAssignments { diff --git a/src/tv2-common/hotkeys/segment.ts b/src/tv2-common/hotkeys/segment.ts index 742d5832f..621d9d52c 100644 --- a/src/tv2-common/hotkeys/segment.ts +++ b/src/tv2-common/hotkeys/segment.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' import { AdlibTags, SharedSourceLayers } from 'tv2-constants' diff --git a/src/tv2-common/hotkeys/server.ts b/src/tv2-common/hotkeys/server.ts index 8df38e639..3eb50fb1c 100644 --- a/src/tv2-common/hotkeys/server.ts +++ b/src/tv2-common/hotkeys/server.ts @@ -1,4 +1,4 @@ -import { IBlueprintTriggeredActions } from '@tv2media/blueprints-integration' +import { IBlueprintTriggeredActions } from 'blueprints-integration' import { DVEBoxTriggers, MakeCutToBoxTrigger } from './helpers' const SERVER_TO_BOX_1_HOTKEYS: string[] = ['Shift+KeyT'] diff --git a/src/tv2-common/hotkeys/sisyfos.ts b/src/tv2-common/hotkeys/sisyfos.ts index 4b2f4af63..6198da93e 100644 --- a/src/tv2-common/hotkeys/sisyfos.ts +++ b/src/tv2-common/hotkeys/sisyfos.ts @@ -6,7 +6,7 @@ import { IGUIContextFilterLink, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal, TRIGGER_HOTKEYS_ON_KEYUP } from 'tv2-common' import { AdlibTags } from 'tv2-constants' diff --git a/src/tv2-common/index.ts b/src/tv2-common/index.ts index 3d5e96e8f..f2f8a3f50 100644 --- a/src/tv2-common/index.ts +++ b/src/tv2-common/index.ts @@ -6,6 +6,7 @@ export * from './cueTiming' export * from './evaluateCues' export * from './frameTime' export * from './getSegment' +export * from './getShowStyleVariantId' export * from './helpers' export * from './hotkeys' export * from './inewsConversion' @@ -20,7 +21,7 @@ export * from './sources' export * from './time/partTime' export * from './atemTransitionStyleFromString' export * from './transitionSettings' -export * from './translateEngine' export * from './types' export * from './updatePolicies' export * from './util' +export * from './showstyle/config-manifests' diff --git a/src/tv2-common/inewsConversion/converters/ParseBody.ts b/src/tv2-common/inewsConversion/converters/ParseBody.ts index 8e14270a8..e221fcc52 100644 --- a/src/tv2-common/inewsConversion/converters/ParseBody.ts +++ b/src/tv2-common/inewsConversion/converters/ParseBody.ts @@ -1,4 +1,4 @@ -import { TSR } from '@tv2media/blueprints-integration' +import { TSR } from 'blueprints-integration' import { AtemTransitionStyleFromString, CueDefinitionFromLayout, @@ -178,6 +178,8 @@ const ACCEPTED_RED_TEXT = [/\b(SERVER|ATTACK|TEKNIK|GRAFIK|EPSIO|VOV?|VOSB)+\b/i const REMOTE_CUE = /^(LIVE|FEED) ?([^\s]+)(?: (.+))?$/i const ENGINE_CUE = /ENGINE ?([^\s]+)/i +const MAX_ALLOWED_TRANSITION_FRAMES = 250 + export function ParseBody( config: TV2BlueprintConfig, segmentId: string, @@ -566,13 +568,18 @@ export function getTransitionProperties(typeStr: string): Pick = getTransitionProperties(typeStr) diff --git a/src/tv2-common/inewsConversion/converters/ParseCue.ts b/src/tv2-common/inewsConversion/converters/ParseCue.ts index fa52631e8..b773c4e5e 100644 --- a/src/tv2-common/inewsConversion/converters/ParseCue.ts +++ b/src/tv2-common/inewsConversion/converters/ParseCue.ts @@ -1,9 +1,8 @@ -import { GetPieceLifespanForGraphic, literal, TableConfigSchema, TV2BlueprintConfig, UnparsedCue } from 'tv2-common' -import { CueType, GraphicEngine, PartType, SourceType } from 'tv2-constants' +import { literal, TableConfigItemGfxDesignTemplate, TV2BlueprintConfig, UnparsedCue } from 'tv2-common' +import { CueType, GraphicEngine, SourceType } from 'tv2-constants' import { getSourceDefinition, getTransitionProperties, - PartDefinition, PartdefinitionTypes, SourceDefinition, SourceDefinitionInvalid, @@ -161,6 +160,11 @@ export interface CueDefinitionPgmClean extends CueDefinitionBase { sourceDefinition: SourceDefinition } +export interface CueDefinitionRobotCamera extends CueDefinitionBase { + type: CueType.RobotCamera + presetIdentifier: number +} + export type CueDefinition = | CueDefinitionUnknown | CueDefinitionEkstern @@ -180,6 +184,7 @@ export type CueDefinition = | CueDefinitionRouting | CueDefinitionPgmClean | CueDefinitionMixMinus + | CueDefinitionRobotCamera export function GraphicIsInternal( o: CueDefinitionGraphic @@ -206,51 +211,51 @@ export function ParseCue(cue: UnparsedCue, config: TV2BlueprintConfig): CueDefin return undefined } - if (cue[0].match(/^[#* ]?kg[= ]ovl-all-out$/i) || cue[0].match(/^[#* ]?kg[= ]altud$/i)) { + if (/^[#* ]?kg[= ]ovl-all-out$/i.test(cue[0]) || /^[#* ]?kg[= ]altud$/i.test(cue[0])) { // All out return parseAllOut(cue) - } else if (cue[0].match(/(?:^[*|#]?kg[ |=])|(?:^digi)/i)) { + } else if (/(?:^[*|#]?kg[ |=])|(?:^digi)/i.test(cue[0])) { // kg (Grafik) return parsekg(cue, config) - } else if (cue[0].match(/^]] [a-z]\d\.\d [a-z] \d \[\[$/i)) { + } else if (/^]] [a-z]\d\.\d [a-z] \d \[\[$/i.test(cue[0])) { // MOS return parsePilot(cue) - } else if (cue[0].match(/[#|*]?cg\d+[ -]pilotdata/i)) { + } else if (/[#|*]?cg\d+[ -]pilotdata/i.test(cue[0])) { return parsePilot(cue) - } else if (cue[0].match(/^EKSTERN=/i)) { + } else if (/^EKSTERN=/i.test(cue[0])) { // EKSTERN return parseEkstern(cue) - } else if (cue[0].match(/^DVE=/i)) { + } else if (/^DVE=/i.test(cue[0])) { // DVE return parseDVE(cue) - } else if (cue[0].match(/^TELEFON=/i)) { + } else if (/^TELEFON=/i.test(cue[0])) { // Telefon return parseTelefon(cue, config) - } else if (cue[0].match(/^(?:SS|GRAFIK)=(?:.*)(?:$| )/i)) { + } else if (/^(?:SS|GRAFIK)=(?:.*)(?:$| )/i.test(cue[0])) { // Target engine return parseTargetEngine(cue, config) - } else if (cue[0].match(/^(?:SS|GRAFIK|VIZ)=(?:full|ovl|wall)(?:$| )/i)) { + } else if (/^(?:SS|GRAFIK|VIZ)=(?:full|ovl|wall)(?:$| )/i.test(cue[0])) { return parseTargetEngine(cue, config) - } else if (cue[0].match(/^VIZ=/i)) { + } else if (/^VIZ=/i.test(cue[0])) { return parseVIZCues(cue) - } else if (cue[0].match(/^STUDIE=MIC ON OFF$/i)) { + } else if (/^STUDIE=MIC ON OFF$/i.test(cue[0])) { return parseMic(cue) - } else if (cue[0].match(/^ADLIBPI?X=/i)) { + } else if (/^ADLIBPI?X=/i.test(cue[0])) { return parseAdLib(cue) - } else if (cue[0].match(/^KOMMANDO=/i)) { + } else if (/^KOMMANDO=/i.test(cue[0])) { return parseKommando(cue) - } else if (cue[0].match(/^LYD=/i)) { + } else if (/^LYD=/i.test(cue[0])) { return parseLYD(cue) - } else if (cue[0].match(/^JINGLE\d+=/i)) { + } else if (/^JINGLE\d+=/i.test(cue[0])) { return parseJingle(cue) - } else if (cue[0].match(/^PGMCLEAN=/i)) { + } else if (/^PGMCLEAN=/i.test(cue[0])) { return parsePgmClean(cue) - } else if (cue[0].match(/^MINUSKAM\s*=/i)) { + } else if (/^MINUSKAM\s*=/i.test(cue[0])) { return parseMixMinus(cue) - } else if (cue[0].match(/^DESIGN_LAYOUT=/i)) { + } else if (/^DESIGN_LAYOUT=/i.test(cue[0])) { return parseDesignLayout(cue, config) - } else if (cue[0].match(/^DESIGN_BG=/i)) { - return parseDesignBg(cue, config) + } else if (/^ROBOT\s*=/i.test(cue[0])) { + return parseRobotCue(cue) } return literal({ @@ -328,24 +333,32 @@ function parsekg( kgCue.graphic = graphic - const graphicConfig = code - ? config.showStyle.GFXTemplates.find( - tmpl => - tmpl.INewsCode.replace(/^KG=?/gi, '#KG').toUpperCase() === code.replace(/^KG=?/gi, '#KG').toUpperCase() && - tmpl.INewsName.toUpperCase() === graphic.template.toUpperCase() + const graphicDesignConfig = code + ? config.showStyle.GfxDesignTemplates.find( + template => template.INewsName.toUpperCase() === graphic.template.toUpperCase() ) : undefined - if (graphicConfig && graphicConfig.IsDesign) { + if (graphicDesignConfig) { return literal({ type: CueType.GraphicDesign, - design: graphicConfig.VizTemplate, + design: graphicDesignConfig.VizTemplate, iNewsCommand: kgCue.iNewsCommand, start: kgCue.start, end: kgCue.end, adlib: kgCue.adlib }) - } else if (graphicConfig && !!graphicConfig.VizTemplate.match(/^VCP$/i)) { + } + + const graphicConfig = code + ? config.showStyle.GFXTemplates.find( + template => + template.INewsCode.replace(/^KG=?/gi, '#KG').toUpperCase() === code.replace(/^KG=?/gi, '#KG').toUpperCase() && + template.INewsName.toUpperCase() === graphic.template.toUpperCase() + ) + : undefined + + if (graphicConfig && !!graphicConfig.VizTemplate.match(/^VCP$/i)) { return literal({ type: CueType.UNPAIRED_TARGET, target: graphicConfig.VizDestination.match(/OVL/i) @@ -706,26 +719,31 @@ function parseTargetEngine( engineCue.routing = routing } + const graphicDesignConfig = code + ? config.showStyle.GfxDesignTemplates.find(template => template.INewsName.toUpperCase() === iNewsName.toUpperCase()) + : undefined + + if (graphicDesignConfig) { + return literal({ + type: CueType.GraphicDesign, + design: graphicDesignConfig.VizTemplate, + iNewsCommand: code, + start: engineCue.start, + end: engineCue.end, + adlib: engineCue.adlib + }) + } + const graphicConfig = config.showStyle.GFXTemplates.find( - tmpl => - tmpl.INewsCode.toUpperCase() === code?.toUpperCase() && tmpl.INewsName.toUpperCase() === iNewsName.toUpperCase() + template => + template.INewsCode.toUpperCase() === code?.toUpperCase() && + template.INewsName.toUpperCase() === iNewsName.toUpperCase() ) if (graphicConfig) { if (!!graphicConfig.VizTemplate.toUpperCase().match(/^VCP$/i)) { engineCue.mergeable = true } else { - if (graphicConfig.IsDesign) { - return literal({ - type: CueType.GraphicDesign, - design: graphicConfig.VizTemplate, - iNewsCommand: code, - start: engineCue.start, - end: engineCue.end, - adlib: engineCue.adlib - }) - } - return literal>({ type: CueType.Graphic, target: engineCue.target, @@ -879,14 +897,16 @@ export function parseTime(line: string): Pick({ type: CueType.GraphicDesign, - design: tableConfigSchema.vizTemplateName, + design: designConfig.VizTemplate, iNewsCommand: layout, start: { frames: 1 @@ -895,109 +915,24 @@ function parseDesignLayout(cue: string[], config: TV2BlueprintConfig): CueDefini }) } -function findSchemaConfiguration(config: TV2BlueprintConfig, designIdentifier: string): TableConfigSchema | undefined { - return config.showStyle.SchemaConfig.find( - schema => schema.designIdentifier && schema.designIdentifier.toUpperCase() === designIdentifier.toUpperCase() +function findGraphicDesignConfiguration( + config: TV2BlueprintConfig, + layout: string +): TableConfigItemGfxDesignTemplate | undefined { + return config.showStyle.GfxDesignTemplates.find( + template => template.INewsStyleColumn && template.INewsStyleColumn.toUpperCase() === layout.toUpperCase() ) } -function parseDesignBg(cue: string[], config: TV2BlueprintConfig): CueDefinitionBackgroundLoop | undefined { - const array = cue[0].split('DESIGN_BG=') - const layout = array[1] - const tableConfigSchema = findSchemaConfiguration(config, layout) - if (!tableConfigSchema) { - return undefined +function parseRobotCue(cue: string[]): CueDefinitionRobotCamera { + const presetIdentifier: number = Number(cue[0].match(/\d+/)) + const time: Pick = cue[1] ? parseTime(cue[1]) : { start: { seconds: 0 } } + return { + type: CueType.RobotCamera, + iNewsCommand: 'RobotCamera', + presetIdentifier, + ...time } - - return literal({ - type: CueType.BackgroundLoop, - target: 'DVE', - backgroundLoop: tableConfigSchema.casparCgDveBgScene, - iNewsCommand: layout, - isFromLayout: true - }) -} - -/** - * Creates a parent class for a part, for keeping children of the parent alive when the parent is alive. - * @param studio Studio name that the part belongs to. - * @param partDefinition Part to create parent string for. - */ -export function PartToParentClass(studio: string, partDefinition: PartDefinition): string | undefined { - switch (partDefinition.type) { - case PartType.Kam: - return CameraParentClass(studio, partDefinition.sourceDefinition.id) - case PartType.Server: - case PartType.VO: - const clip = partDefinition.fields.videoId - - if (clip) { - return ServerParentClass(studio, clip) - } else { - return - } - case PartType.EVS: - return EVSParentClass(studio, partDefinition.sourceDefinition.id) - default: - return UnknownPartParentClass(studio, partDefinition) - } -} - -export function CameraParentClass(studio: string, cameraName: string) { - return `${studio.toLowerCase()}_parent_camera_${cameraName.toLowerCase().replace(/\W/, '_')}` -} - -export function EksternParentClass(studio: string, source: string) { - return `${studio.toLowerCase()}_parent_ekstern_${source.toLowerCase().replace(/\W/, '_')}` -} - -export function ServerParentClass(studio: string, clip: string) { - return `${studio.toLowerCase()}_parent_server_${clip.toLowerCase().replace(/\W/, '_')}` -} - -export function EVSParentClass(studio: string, evs: string) { - return `${studio.toLowerCase()}_parent_evs_${evs.toLowerCase().replace(/\W/, '_')}` -} - -export function DVEParentClass(studio: string, dve: string) { - return `${studio.toLowerCase()}_parent_dve_${dve.toLowerCase().replace(/\W/, '_')}` -} - -export function TLFParentClass(studio: string, source: string) { - return `${studio.toLowerCase()}_parent_tlf_${source.toLowerCase().replace(/\W/, '_')}` -} - -export function UnknownPartParentClass(studio: string, partDefinition: PartDefinition): string | undefined { - const firstCue = partDefinition.cues.find(c => [CueType.DVE, CueType.Ekstern, CueType.Telefon].includes(c.type)) - - if (!firstCue) { - return - } - - switch (firstCue.type) { - case CueType.DVE: - return DVEParentClass(studio, firstCue.template) - case CueType.Ekstern: - return EksternParentClass(studio, firstCue.sourceDefinition.name) - case CueType.Telefon: - return TLFParentClass(studio, firstCue.source) - default: - return - } -} - -export function AddParentClass(config: TV2BlueprintConfig, partDefinition: PartDefinition) { - if ( - partDefinition.cues.some( - cue => cue.start === CueType.Graphic && cue.end && cue.end.infiniteMode && cue.end.infiniteMode === 'B' - ) - ) { - return true - } - - return partDefinition.cues.some( - c => c.type === CueType.Graphic && GraphicIsInternal(c) && GetPieceLifespanForGraphic(c.target, config, c) - ) } export function UnpairedPilotToGraphic( diff --git a/src/tv2-common/inewsConversion/converters/__tests__/body-parser.spec.ts b/src/tv2-common/inewsConversion/converters/__tests__/body-parser.spec.ts index b6e578307..e48fcb1d0 100644 --- a/src/tv2-common/inewsConversion/converters/__tests__/body-parser.spec.ts +++ b/src/tv2-common/inewsConversion/converters/__tests__/body-parser.spec.ts @@ -1,7 +1,9 @@ -import { IBlueprintRundownDB, PlaylistTimingType, TSR } from '@tv2media/blueprints-integration' +import { IBlueprintRundownDB, PlaylistTimingType, TSR } from 'blueprints-integration' import { CueDefinitionBackgroundLoop, CueDefinitionGraphicDesign, + getTransitionProperties, + PartdefinitionTypes, stripRedundantCuesWhenLayoutCueIsPresent, UnparsedCue } from 'tv2-common' @@ -3493,6 +3495,32 @@ describe('Body parser', () => { expect(result).toEqual(definitions) }) }) + + describe('getTransitionProperties', () => { + it('has a Dip transition lasting 4 frames, transition.duration is 4', () => { + const iNewsCue = 'SOME PART DIP 4' + + const result: Pick = getTransitionProperties(iNewsCue) + + expect(result.transition!.duration).toBe(4) + }) + + it('has a Dip transition lasting 10 frames, transition.duration is 10', () => { + const iNewsCue = 'SOME PART DIP 10' + + const result: Pick = getTransitionProperties(iNewsCue) + + expect(result.transition!.duration).toBe(10) + }) + + it('has a Dip transition lasting more than the max allowed 250 frames, transition.duration is 250', () => { + const iNewsCue = 'SOME PART DIP 231342143' + + const result: Pick = getTransitionProperties(iNewsCue) + + expect(result.transition!.duration).toBe(250) + }) + }) }) function createPartDefinition(cues?: CueDefinition[]): PartDefinition { 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 385fa803d..fb1092b6d 100644 --- a/src/tv2-common/inewsConversion/converters/__tests__/cue-parser.spec.ts +++ b/src/tv2-common/inewsConversion/converters/__tests__/cue-parser.spec.ts @@ -1,5 +1,5 @@ -import { IBlueprintRundownDB, PlaylistTimingType, TSR } from '@tv2media/blueprints-integration' -import { RemoteType, SourceDefinitionKam, SourceDefinitionRemote } from 'tv2-common' +import { IBlueprintRundownDB, PlaylistTimingType, TSR } from 'blueprints-integration' +import { CueDefinitionRobotCamera, RemoteType, SourceDefinitionKam, SourceDefinitionRemote } from 'tv2-common' import { CueType, SourceType } from 'tv2-constants' import { SegmentUserContext } from '../../../../__mocks__/context' import { defaultShowStyleConfig, defaultStudioConfig } from '../../../../tv2_afvd_showstyle/__tests__/configs' @@ -599,6 +599,26 @@ describe('Cue parser', () => { ) }) + test('Grafik (kg) - direkte - create adlib when extra lines', () => { + const cueGrafik = ['#kg direkte KØBENHAVN', '', ';x.xx'] + const result = ParseCue(cueGrafik, config) + expect(result).toEqual( + literal>({ + type: CueType.Graphic, + target: 'OVL', + + graphic: { + type: 'internal', + template: 'direkte', + cue: '#kg', + textFields: ['KØBENHAVN'] + }, + adlib: true, + iNewsCommand: '#kg' + }) + ) + }) + test('Grafik (kg) - BillederFra_logo', () => { const cueGrafik = ['#kg BillederFra_logo KØBENHAVN', ';0.01'] const result = ParseCue(cueGrafik, config) @@ -644,13 +664,13 @@ describe('Cue parser', () => { ) }) - test('KG=DESIGN_FODBOLD', () => { - const cueGrafik = ['KG=DESIGN_FODBOLD_20', ';0.00.01'] + test('Find KG=DESIGN_FODBOLD in design templates', () => { + const cueGrafik = ['KG=DESIGN_FODBOLD_22', ';0.00.01'] const result = ParseCue(cueGrafik, config) expect(result).toEqual( literal({ type: CueType.GraphicDesign, - design: 'DESIGN_FODBOLD_20', + design: 'DESIGN_FODBOLD_22', start: { frames: 1, seconds: 0 @@ -905,6 +925,48 @@ describe('Cue parser', () => { ) }) + test('#cg4 pilotdata with non-digit VCPID defaults to -1', () => { + const cueMOS = [ + '#cg4 pilotdata', + 'TELEFON/KORT//LIVE_KABUL', + 'VCPID=abc', + 'ContinueCount=3', + 'TELEFON/KORT//LIVE_KABUL' + ] + const result = ParseCue(cueMOS, config) + expect(result).toEqual( + literal({ + type: CueType.UNPAIRED_PILOT, + name: '', + vcpid: -1, + continueCount: -1, + engineNumber: 4, + iNewsCommand: 'VCP' + }) + ) + }) + + test('#cg4 pilotdata with empty VCPID defaults to -1', () => { + const cueMOS = [ + '#cg4 pilotdata', + 'TELEFON/KORT//LIVE_KABUL', + 'VCPID=', + 'ContinueCount=3', + 'TELEFON/KORT//LIVE_KABUL' + ] + const result = ParseCue(cueMOS, config) + expect(result).toEqual( + literal({ + type: CueType.UNPAIRED_PILOT, + name: '', + vcpid: -1, + continueCount: -1, + engineNumber: 4, + iNewsCommand: 'VCP' + }) + ) + }) + test('GRAFIK=FULL', () => { const cueGrafik = ['GRAFIK=FULL', 'INP1=', 'INP='] const result = ParseCue(cueGrafik, config) @@ -1644,209 +1706,241 @@ describe('Cue parser', () => { ) }) - /** All-out cues */ - /** These tests are also used to catch case sensitivity / cue start symbols */ - test('All out', () => { - const cueViz = ['KG=ovl-all-out', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: 'KG' - }) - ) - }) + describe('All-out cues', () => { + /** These tests are also used to catch case sensitivity / cue start symbols */ + test('All out', () => { + const cueViz = ['KG=ovl-all-out', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: 'KG' + }) + ) + }) - test('All out', () => { - const cueViz = ['KG ovl-all-out', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: 'KG' - }) - ) - }) + test('All out', () => { + const cueViz = ['KG ovl-all-out', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: 'KG' + }) + ) + }) - test('All out', () => { - const cueViz = ['kg=ovl-all-out', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: 'kg' - }) - ) - }) + test('All out', () => { + const cueViz = ['kg=ovl-all-out', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: 'kg' + }) + ) + }) - test('All out', () => { - const cueViz = ['kg ovl-all-out', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: 'kg' - }) - ) - }) + test('All out', () => { + const cueViz = ['kg ovl-all-out', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: 'kg' + }) + ) + }) - test('All out', () => { - const cueViz = ['#KG=ovl-all-out', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: '#KG' - }) - ) - }) + test('All out', () => { + const cueViz = ['#KG=ovl-all-out', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: '#KG' + }) + ) + }) - test('All out', () => { - const cueViz = ['#KG ovl-all-out', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: '#KG' - }) - ) - }) + test('All out', () => { + const cueViz = ['#KG ovl-all-out', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: '#KG' + }) + ) + }) - test('All out', () => { - const cueViz = ['#kg=ovl-all-out', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: '#kg' - }) - ) - }) + test('All out', () => { + const cueViz = ['#kg=ovl-all-out', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: '#kg' + }) + ) + }) - test('All out', () => { - const cueViz = ['#kg ovl-all-out', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: '#kg' - }) - ) - }) + test('All out', () => { + const cueViz = ['#kg ovl-all-out', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: '#kg' + }) + ) + }) - test('All out', () => { - const cueViz = ['kg altud', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: 'kg' - }) - ) - }) + test('All out', () => { + const cueViz = ['kg altud', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: 'kg' + }) + ) + }) - test('All out', () => { - const cueViz = ['kg=altud', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: 'kg' - }) - ) - }) + test('All out', () => { + const cueViz = ['kg=altud', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: 'kg' + }) + ) + }) - test('All out', () => { - const cueViz = ['kg altud', ';0.00.01'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - start: { - frames: 1, - seconds: 0 - }, - iNewsCommand: 'kg' - }) - ) - }) + test('All out', () => { + const cueViz = ['kg altud', ';0.00.01'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + start: { + frames: 1, + seconds: 0 + }, + iNewsCommand: 'kg' + }) + ) + }) - test('All out', () => { - const cueViz = ['kg altud', ';0.0x'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - adlib: true, - iNewsCommand: 'kg' - }) - ) - }) + test('All out', () => { + const cueViz = ['kg altud', ';0.0x'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + adlib: true, + iNewsCommand: 'kg' + }) + ) + }) - test('All out', () => { - const cueViz = ['kg altud', ';x.xx'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.ClearGrafiks, - adlib: true, - iNewsCommand: 'kg' - }) - ) - }) + test('All out', () => { + const cueViz = ['kg altud', ';x.xx'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.ClearGrafiks, + adlib: true, + iNewsCommand: 'kg' + }) + ) + }) - test('All out', () => { - const cueViz = ['LYD=SN_intro', ';0.0x'] - const result = ParseCue(cueViz, config) - expect(result).toEqual( - literal({ - type: CueType.LYD, - adlib: true, - variant: 'SN_intro', - iNewsCommand: 'LYD' - }) - ) + test('All out', () => { + const cueViz = ['LYD=SN_intro', ';0.0x'] + const result = ParseCue(cueViz, config) + expect(result).toEqual( + literal({ + type: CueType.LYD, + adlib: true, + variant: 'SN_intro', + iNewsCommand: 'LYD' + }) + ) + }) }) - /** End of all-out cues */ + describe('Robot cue', () => { + it("receives 'ROBOT', returns a cue with type RobotCamera", () => { + const cue = ['ROBOT=s2'] + const result = ParseCue(cue, config) as CueDefinitionRobotCamera + expect(result.type).toBe(CueType.RobotCamera) + }) + + it("receives 'ROBOT=s2', preset is 2", () => { + const cue = ['ROBOT=s2'] + const result = ParseCue(cue, config) as CueDefinitionRobotCamera + expect(result!.presetIdentifier).toBe(2) + }) + + it("receives 'ROBOT=s5', preset is 5", () => { + const cue = ['ROBOT=s5'] + const result = ParseCue(cue, config) as CueDefinitionRobotCamera + expect(result!.presetIdentifier).toBe(5) + }) + + it("receives 'ROBOT=11', preset is 11", () => { + const cue = ['ROBOT=11'] + const result = ParseCue(cue, config) as CueDefinitionRobotCamera + expect(result!.presetIdentifier).toBe(11) + }) + + it('receives time code ;0.24.10, start is 24 seconds and 10 frames', () => { + const cue = ['ROBOT=11', '0.24.10'] + const result = ParseCue(cue, config) as CueDefinitionRobotCamera + expect(result!.start!.seconds).toBe(24) + expect(result!.start!.frames).toBe(10) + }) + }) }) diff --git a/src/tv2-common/inewsConversion/converters/__tests__/part-to-parent-class.spec.ts b/src/tv2-common/inewsConversion/converters/__tests__/part-to-parent-class.spec.ts deleted file mode 100644 index 6a55df041..000000000 --- a/src/tv2-common/inewsConversion/converters/__tests__/part-to-parent-class.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { literal } from 'tv2-common' -import { CueType, PartType, SourceType } from 'tv2-constants' -import { PartDefinitionEkstern, RemoteType } from '../ParseBody' -import { CueDefinitionEkstern, PartToParentClass } from '../ParseCue' - -describe('PartToParentClass', () => { - it('Creates class for Ekstern', () => { - const partDefinition = literal({ - type: PartType.REMOTE, - externalId: '', - rawType: '', - cues: [ - literal({ - type: CueType.Ekstern, - sourceDefinition: { - sourceType: SourceType.REMOTE, - remoteType: RemoteType.LIVE, - id: '1', - raw: 'Live 1', - name: 'LIVE 1' - }, - iNewsCommand: 'EKSTERN' - }) - ], - script: '', - fields: {}, - modified: 0, - storyName: '', - segmentExternalId: '' - }) - const result = PartToParentClass('studio0', partDefinition) - expect(result).toBe('studio0_parent_ekstern_live_1') - }) -}) diff --git a/src/tv2-common/jinglePartProperties.ts b/src/tv2-common/jinglePartProperties.ts index d16da3f78..6b848bff5 100644 --- a/src/tv2-common/jinglePartProperties.ts +++ b/src/tv2-common/jinglePartProperties.ts @@ -1,4 +1,4 @@ -import { IBlueprintPart, IShowStyleUserContext } from '@tv2media/blueprints-integration' +import { IBlueprintPart, IShowStyleUserContext } from 'blueprints-integration' import { CueType } from 'tv2-constants' import { TableConfigItemBreakers, TV2BlueprintConfigBase, TV2StudioConfigBase } from './blueprintConfig' import { TimeFromFrames } from './frameTime' diff --git a/src/tv2-common/layers/sourceLayers.ts b/src/tv2-common/layers/sourceLayers.ts index e52a0b919..c975969d1 100644 --- a/src/tv2-common/layers/sourceLayers.ts +++ b/src/tv2-common/layers/sourceLayers.ts @@ -1,4 +1,4 @@ -import { ISourceLayer, SourceLayerType } from '@tv2media/blueprints-integration' +import { ISourceLayer, SourceLayerType } from 'blueprints-integration' import { ATEMModel } from '../../types/atem' import { GetDSKCount } from '../helpers' diff --git a/src/tv2-common/layers/timelineLayers.ts b/src/tv2-common/layers/timelineLayers.ts index 0e1188edf..ed1d23570 100644 --- a/src/tv2-common/layers/timelineLayers.ts +++ b/src/tv2-common/layers/timelineLayers.ts @@ -1,4 +1,4 @@ -import { BlueprintMapping, BlueprintMappings, LookaheadMode, TSR } from '@tv2media/blueprints-integration' +import { BlueprintMapping, BlueprintMappings, LookaheadMode, TSR } from 'blueprints-integration' import { literal } from 'tv2-common' import { ATEMModel } from '../../types/atem' import { GetDSKCount } from '../helpers' diff --git a/src/tv2-common/migrations/__tests__/dve-config-folder.spec.ts b/src/tv2-common/migrations/__tests__/dve-config-folder.spec.ts index 612b23498..e459b9128 100644 --- a/src/tv2-common/migrations/__tests__/dve-config-folder.spec.ts +++ b/src/tv2-common/migrations/__tests__/dve-config-folder.spec.ts @@ -1,4 +1,4 @@ -import { ConfigItemValue, TableConfigItemValue } from '@tv2media/blueprints-integration' +import { ConfigItemValue, TableConfigItemValue } from 'blueprints-integration' import { literal, StripFolderFromDVEConfig } from 'tv2-common' import { MockShowstyleMigrationContext } from './migrationContext.mock' diff --git a/src/tv2-common/migrations/__tests__/migrationContext.mock.ts b/src/tv2-common/migrations/__tests__/migrationContext.mock.ts index 252686982..ec2a8a39c 100644 --- a/src/tv2-common/migrations/__tests__/migrationContext.mock.ts +++ b/src/tv2-common/migrations/__tests__/migrationContext.mock.ts @@ -7,7 +7,7 @@ import { MigrationContextShowStyle, OmitId, ShowStyleVariantPart -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' export class MockShowstyleMigrationContext implements MigrationContextShowStyle { public variants: IBlueprintShowStyleVariant[] = [] diff --git a/src/tv2-common/migrations/__tests__/soundbed-config-audio-folder.spec.ts b/src/tv2-common/migrations/__tests__/soundbed-config-audio-folder.spec.ts index 98696b9ba..7e0fb8f81 100644 --- a/src/tv2-common/migrations/__tests__/soundbed-config-audio-folder.spec.ts +++ b/src/tv2-common/migrations/__tests__/soundbed-config-audio-folder.spec.ts @@ -1,4 +1,4 @@ -import { ConfigItemValue, TableConfigItemValue } from '@tv2media/blueprints-integration' +import { ConfigItemValue, TableConfigItemValue } from 'blueprints-integration' import { literal, StripFolderFromAudioBedConfig } from 'tv2-common' import { MockShowstyleMigrationContext } from './migrationContext.mock' diff --git a/src/tv2-common/migrations/addKeepAudio.ts b/src/tv2-common/migrations/addKeepAudio.ts index c6629842c..a36cb7604 100644 --- a/src/tv2-common/migrations/addKeepAudio.ts +++ b/src/tv2-common/migrations/addKeepAudio.ts @@ -1,4 +1,4 @@ -import { MigrationContextStudio, MigrationStepStudio, TableConfigItemValue } from '@tv2media/blueprints-integration' +import { MigrationContextStudio, MigrationStepStudio, TableConfigItemValue } from 'blueprints-integration' import * as _ from 'underscore' export function AddKeepAudio(versionStr: string, configName: string): MigrationStepStudio { diff --git a/src/tv2-common/migrations/forceSourceLayerToDefaultsBase.ts b/src/tv2-common/migrations/forceSourceLayerToDefaultsBase.ts index 137fad578..9e7dd8040 100644 --- a/src/tv2-common/migrations/forceSourceLayerToDefaultsBase.ts +++ b/src/tv2-common/migrations/forceSourceLayerToDefaultsBase.ts @@ -1,4 +1,4 @@ -import { ISourceLayer, MigrationContextShowStyle, MigrationStepShowStyle } from '@tv2media/blueprints-integration' +import { ISourceLayer, MigrationContextShowStyle, MigrationStepShowStyle } from 'blueprints-integration' import _ = require('underscore') export function forceSourceLayerToDefaultsBase( diff --git a/src/tv2-common/migrations/graphic-defaults.ts b/src/tv2-common/migrations/graphic-defaults.ts index 87ec64d88..3f7bf9075 100644 --- a/src/tv2-common/migrations/graphic-defaults.ts +++ b/src/tv2-common/migrations/graphic-defaults.ts @@ -1,6 +1,15 @@ -import { TV2ShowstyleBlueprintConfigBase } from '../blueprintConfig' +export interface TableConfigItemGfxTemplateWithDesign { + VizTemplate: string + SourceLayer: string + LayerMapping: string + INewsCode: string + INewsName: string + VizDestination: string + OutType: string + IsDesign: boolean +} -export const DEFAULT_GRAPHICS: TV2ShowstyleBlueprintConfigBase['GFXTemplates'] = [ +export const DEFAULT_GRAPHICS: TableConfigItemGfxTemplateWithDesign[] = [ { INewsCode: '#kg', INewsName: 'arkiv', diff --git a/src/tv2-common/migrations/hotkeys.ts b/src/tv2-common/migrations/hotkeys.ts index de3283127..fbb8961b2 100644 --- a/src/tv2-common/migrations/hotkeys.ts +++ b/src/tv2-common/migrations/hotkeys.ts @@ -3,7 +3,7 @@ import { ISourceLayer, MigrationContextShowStyle, MigrationStepShowStyle -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { defaultHotkeys, GlobalHotkeySourceLayers, diff --git a/src/tv2-common/migrations/index.ts b/src/tv2-common/migrations/index.ts index 33e1da474..2086cd887 100644 --- a/src/tv2-common/migrations/index.ts +++ b/src/tv2-common/migrations/index.ts @@ -6,10 +6,11 @@ import { MigrationStepShowStyle, MigrationStepStudio, TableConfigItemValue -} from '@tv2media/blueprints-integration' -import { TableConfigItemGFXTemplates, TableConfigItemSourceMappingWithSisyfos } from 'tv2-common' +} from 'blueprints-integration' +import { TableConfigItemGfxDesignTemplate, TableConfigItemSourceMappingWithSisyfos } from 'tv2-common' import _ = require('underscore') import { literal } from '../util' +import { TableConfigItemGfxTemplateWithDesign } from './graphic-defaults' export * from './moveSourcesToTable' export * from './addKeepAudio' @@ -94,17 +95,19 @@ export function removeSourceLayer(versionStr: string, studioId: string, layer: s }) } -export function AddGraphicToGFXTable( +export function AddGraphicToGfxTable( versionStr: string, studio: string, - config: TableConfigItemGFXTemplates + config: TableConfigItemGfxTemplateWithDesign ): MigrationStepShowStyle { return { id: `${versionStr}.gfxConfig.add${config.INewsName}.${studio}`, version: versionStr, canBeRunAutomatically: true, validate: (context: MigrationContextShowStyle) => { - const existing = (context.getBaseConfig('GFXTemplates') as unknown) as TableConfigItemGFXTemplates[] | undefined + const existing = (context.getBaseConfig('GFXTemplates') as unknown) as + | TableConfigItemGfxTemplateWithDesign[] + | undefined if (!existing || !existing.length) { return false @@ -116,7 +119,7 @@ export function AddGraphicToGFXTable( ) }, migrate: (context: MigrationContextShowStyle) => { - const existing = (context.getBaseConfig('GFXTemplates') as unknown) as TableConfigItemGFXTemplates[] + const existing = (context.getBaseConfig('GFXTemplates') as unknown) as TableConfigItemGfxTemplateWithDesign[] existing.push(config) @@ -125,6 +128,51 @@ export function AddGraphicToGFXTable( } } +export function mapGfxTemplateToDesignTemplateAndDeleteOriginals( + versionStr: string, + studio: string, + from: string, + to: string +) { + return literal({ + id: `${versionStr}.mapGFXTemplateToDesignTemplateAndDeleteOriginals.${from}.${studio}`, + version: versionStr, + canBeRunAutomatically: true, + validate: (context: MigrationContextShowStyle) => { + const gfxTemplates = (context.getBaseConfig(from) as unknown) as + | TableConfigItemGfxTemplateWithDesign[] + | undefined + + const designTemplates = (context.getBaseConfig(to) as unknown) as TableConfigItemGfxDesignTemplate[] | undefined + + if (!gfxTemplates || !gfxTemplates.length) { + return false + } + + if (designTemplates && designTemplates.length) { + return false + } + + return gfxTemplates.some(template => template.IsDesign) + }, + migrate: (context: MigrationContextShowStyle) => { + const gfxTemplates = (context.getBaseConfig(from) as unknown) as TableConfigItemGfxTemplateWithDesign[] + const designTemplates = ((context.getBaseConfig(to) as unknown) as TableConfigItemGfxDesignTemplate[]) ?? [] + + gfxTemplates + .filter(template => template.IsDesign) + .map(template => { + designTemplates.push({ ...template, INewsStyleColumn: '' }) + }) + + const newGfxTemplates = gfxTemplates.filter(template => !template.IsDesign) + + context.setBaseConfig(from, (newGfxTemplates as unknown) as ConfigItemValue) + context.setBaseConfig(to, (designTemplates as unknown) as ConfigItemValue) + } + }) +} + export function addSourceToSourcesConfig( versionStr: string, studio: string, @@ -151,11 +199,11 @@ export function addSourceToSourcesConfig( } } -export function changeGFXTemplate( +export function changeGfxTemplate( versionStr: string, studio: string, - oldConfig: Partial, - config: Partial + oldConfig: Partial, + config: Partial ): MigrationStepShowStyle { const keysToUpdate = Object.keys(config).join('_') return { @@ -164,7 +212,7 @@ export function changeGFXTemplate( canBeRunAutomatically: true, validate: (context: MigrationContextShowStyle) => { const gfxTemplates = (context.getBaseConfig('GFXTemplates') as unknown) as - | TableConfigItemGFXTemplates[] + | TableConfigItemGfxTemplateWithDesign[] | undefined if (!gfxTemplates || !gfxTemplates.length) { @@ -174,7 +222,7 @@ export function changeGFXTemplate( return gfxTemplates.some(g => isGfxTemplateSubset(g, oldConfig)) }, migrate: (context: MigrationContextShowStyle) => { - let existing = (context.getBaseConfig('GFXTemplates') as unknown) as TableConfigItemGFXTemplates[] + let existing = (context.getBaseConfig('GFXTemplates') as unknown) as TableConfigItemGfxTemplateWithDesign[] existing = existing.map(g => (isGfxTemplateSubset(g, oldConfig) ? { ...g, ...config } : g)) @@ -184,10 +232,10 @@ export function changeGFXTemplate( } function isGfxTemplateSubset( - superset: Partial, - subset: Partial + superset: Partial, + subset: Partial ): boolean { - return Object.keys(subset).every((key: keyof TableConfigItemGFXTemplates) => superset[key] === subset[key]) + return Object.keys(subset).every((key: keyof TableConfigItemGfxTemplateWithDesign) => superset[key] === subset[key]) } export function SetLayerNamesToDefaults( @@ -368,3 +416,35 @@ export function PrefixEvsWithEvs( } } } + +export function renameTableColumn( + versionStr: string, + tableId: string, + oldColumnId: string, + newColumnId: string +): MigrationStepShowStyle { + return { + id: `${versionStr}.renameTableColumn.${tableId}.${oldColumnId}`, + version: versionStr, + canBeRunAutomatically: true, + validate: (context: MigrationContextShowStyle) => { + const config = (context.getBaseConfig(tableId) as unknown) as TableConfigItemValue + + if (!config || !Array.isArray(config)) { + return false + } + + return config.find(row => oldColumnId in row) !== undefined + }, + migrate: (context: MigrationContextShowStyle) => { + let config = (context.getBaseConfig(tableId) as unknown) as TableConfigItemValue + config = config.map(row => { + const value = row[oldColumnId] + delete row[oldColumnId] + row[newColumnId] = value + return row + }) + context.setBaseConfig(tableId, (config as unknown) as ConfigItemValue) + } + } +} diff --git a/src/tv2-common/migrations/manifestWithMediaFlow.ts b/src/tv2-common/migrations/manifestWithMediaFlow.ts index 5f3d4f112..9b8e9e406 100644 --- a/src/tv2-common/migrations/manifestWithMediaFlow.ts +++ b/src/tv2-common/migrations/manifestWithMediaFlow.ts @@ -1,4 +1,4 @@ -import { ConfigManifestEntry, ConfigManifestEntryType } from '@tv2media/blueprints-integration' +import { ConfigManifestEntry, ConfigManifestEntryType } from 'blueprints-integration' export function MakeConfigWithMediaFlow( name: string, diff --git a/src/tv2-common/migrations/moveSourcesToTable.ts b/src/tv2-common/migrations/moveSourcesToTable.ts index bc8c5cd49..33e873805 100644 --- a/src/tv2-common/migrations/moveSourcesToTable.ts +++ b/src/tv2-common/migrations/moveSourcesToTable.ts @@ -1,4 +1,4 @@ -import { MigrationContextStudio, MigrationStepStudio, TableConfigItemValue } from '@tv2media/blueprints-integration' +import { MigrationContextStudio, MigrationStepStudio, TableConfigItemValue } from 'blueprints-integration' import { parseMapStr, TableConfigItemSourceMapping, TableConfigItemSourceMappingWithSisyfos } from 'tv2-common' import * as _ from 'underscore' import { literal } from '../util' diff --git a/src/tv2-common/migrations/sourceLayers.ts b/src/tv2-common/migrations/sourceLayers.ts index 84b613346..906ce9a5c 100644 --- a/src/tv2-common/migrations/sourceLayers.ts +++ b/src/tv2-common/migrations/sourceLayers.ts @@ -1,4 +1,4 @@ -import { ISourceLayer, MigrationContextShowStyle, MigrationStepShowStyle } from '@tv2media/blueprints-integration' +import { ISourceLayer, MigrationContextShowStyle, MigrationStepShowStyle } from 'blueprints-integration' import { WithValuesOfTypes } from 'tv2-common' import _ = require('underscore') diff --git a/src/tv2-common/migrations/sourceManifest.ts b/src/tv2-common/migrations/sourceManifest.ts index 3d180ebaa..10d7758d3 100644 --- a/src/tv2-common/migrations/sourceManifest.ts +++ b/src/tv2-common/migrations/sourceManifest.ts @@ -1,4 +1,4 @@ -import { ConfigManifestEntryTable, ConfigManifestEntryType, TSR } from '@tv2media/blueprints-integration' +import { ConfigManifestEntryTable, ConfigManifestEntryType, TSR } from 'blueprints-integration' import { literal } from '../util' export function MakeConfigForSources( diff --git a/src/tv2-common/migrations/transitions.ts b/src/tv2-common/migrations/transitions.ts index c6e7e353b..d405548ee 100644 --- a/src/tv2-common/migrations/transitions.ts +++ b/src/tv2-common/migrations/transitions.ts @@ -1,4 +1,4 @@ -import { MigrationContextShowStyle, MigrationStepShowStyle } from '@tv2media/blueprints-integration' +import { MigrationContextShowStyle, MigrationStepShowStyle } from 'blueprints-integration' import { literal } from 'tv2-common' import { TableConfigItemAdLibTransitions } from '../blueprintConfig' diff --git a/src/tv2-common/onTimelineGenerate.ts b/src/tv2-common/onTimelineGenerate.ts index 9d6fe0a8b..5a832fe72 100644 --- a/src/tv2-common/onTimelineGenerate.ts +++ b/src/tv2-common/onTimelineGenerate.ts @@ -11,9 +11,9 @@ import { TimelineObjectCoreExt, TimelinePersistentState, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionSelectFullGrafik, ActionSelectJingle, ActionSelectServerClip, CasparPlayerClip } from 'tv2-common' -import { AbstractLLayer, TallyTags } from 'tv2-constants' +import { AbstractLLayer, PartType, TallyTags } from 'tv2-constants' import * as _ from 'underscore' import { SisyfosLLAyer } from '../tv2_afvd_studio/layers' import { TV2BlueprintConfigBase, TV2StudioConfigBase } from './blueprintConfig' @@ -59,7 +59,8 @@ export interface PieceMetaData { } export interface GraphicPieceMetaData extends PieceMetaData { - belongsToRemotePart?: boolean + partType?: PartType + pieceExternalId?: string } export interface JinglePieceMetaData extends PieceMetaData { diff --git a/src/tv2-common/parts/effekt.ts b/src/tv2-common/parts/effekt.ts index 68a4cef3f..fb8e0886f 100644 --- a/src/tv2-common/parts/effekt.ts +++ b/src/tv2-common/parts/effekt.ts @@ -8,7 +8,7 @@ import { TSR, VTContent, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionTakeWithTransitionVariantDip, ActionTakeWithTransitionVariantMix, @@ -24,7 +24,7 @@ import { } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' import { TV2BlueprintConfig } from '../blueprintConfig' -import { JoinAssetToFolder, JoinAssetToNetworkPath } from '../util' +import { joinAssetToFolder, joinAssetToNetworkPath } from '../util' /** Has to be executed before calling EvaluateCues, as some cues may depend on it */ export function CreateEffektForPartBase( @@ -116,7 +116,7 @@ export function CreateEffektForPartInner< return false } - const fileName = JoinAssetToFolder(config.studio.JingleFolder, file) + const fileName = joinAssetToFolder(config.studio.JingleFolder, file) pieces.push({ externalId, @@ -128,7 +128,7 @@ export function CreateEffektForPartInner< pieceType: IBlueprintPieceType.InTransition, content: literal>({ fileName, - path: JoinAssetToNetworkPath( + path: joinAssetToNetworkPath( config.studio.JingleNetworkBasePath, config.studio.JingleFolder, file, diff --git a/src/tv2-common/parts/invalid.ts b/src/tv2-common/parts/invalid.ts index b7b1a2cf8..4b650bd37 100644 --- a/src/tv2-common/parts/invalid.ts +++ b/src/tv2-common/parts/invalid.ts @@ -1,4 +1,4 @@ -import { BlueprintResultPart, IBlueprintPart } from '@tv2media/blueprints-integration' +import { BlueprintResultPart, IBlueprintPart } from 'blueprints-integration' import { PartDefinition } from 'tv2-common' export function CreatePartInvalid(ingestPart: PartDefinition, externalIdSuffix?: string): BlueprintResultPart { diff --git a/src/tv2-common/parts/kam.ts b/src/tv2-common/parts/kam.ts index ebd6bdbc1..64bfecc27 100644 --- a/src/tv2-common/parts/kam.ts +++ b/src/tv2-common/parts/kam.ts @@ -1,4 +1,4 @@ -import { BlueprintResultPart, IBlueprintPart, IShowStyleUserContext } from '@tv2media/blueprints-integration' +import { BlueprintResultPart, IBlueprintPart, IShowStyleUserContext } from 'blueprints-integration' import { PartDefinition, PartTime, TV2BlueprintConfigBase, TV2StudioConfigBase } from 'tv2-common' export function CreatePartKamBase< diff --git a/src/tv2-common/parts/server.ts b/src/tv2-common/parts/server.ts index 56dd40854..3a7ceb640 100644 --- a/src/tv2-common/parts/server.ts +++ b/src/tv2-common/parts/server.ts @@ -6,7 +6,7 @@ import { PieceLifespan, VTContent, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CutToServer, GetTagForServer, @@ -204,7 +204,6 @@ function getContentServerElement< StudioConfig extends TV2StudioConfigBase, ShowStyleConfig extends TV2BlueprintConfigBase >( - partDefinition: PartDefinition, partProps: ServerPartProps, contentProps: ServerContentProps, layers: ServerPartLayers, @@ -213,7 +212,6 @@ function getContentServerElement< ): WithTimeline { return MakeContentServer( context, - partDefinition, config, { Caspar: { @@ -245,7 +243,7 @@ function getServerSelectionBlueprintPiece< prerollDuration: number ): IBlueprintPiece { const userDataElement = getUserData(partDefinition, contentProps.file, actualDuration, partProps) - const contentServerElement = getContentServerElement(partDefinition, partProps, contentProps, layers, context, config) + const contentServerElement = getContentServerElement(partProps, contentProps, layers, context, config) return { externalId: partDefinition.externalId, diff --git a/src/tv2-common/pieces/adlibServer.ts b/src/tv2-common/pieces/adlibServer.ts index 411786821..7d83b1a6d 100644 --- a/src/tv2-common/pieces/adlibServer.ts +++ b/src/tv2-common/pieces/adlibServer.ts @@ -1,4 +1,4 @@ -import { IBlueprintActionManifest, IShowStyleUserContext } from '@tv2media/blueprints-integration' +import { IBlueprintActionManifest, IShowStyleUserContext } from 'blueprints-integration' import { ActionSelectServerClip, getSourceDuration, diff --git a/src/tv2-common/pieces/script.ts b/src/tv2-common/pieces/script.ts index 66830e66a..db2198cad 100644 --- a/src/tv2-common/pieces/script.ts +++ b/src/tv2-common/pieces/script.ts @@ -1,4 +1,4 @@ -import { IBlueprintPiece, PieceLifespan, ScriptContent, WithTimeline } from '@tv2media/blueprints-integration' +import { IBlueprintPiece, PieceLifespan, ScriptContent, WithTimeline } from 'blueprints-integration' import { literal, PartDefinition } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' diff --git a/src/tv2-common/pieces/telemetric.ts b/src/tv2-common/pieces/telemetric.ts new file mode 100644 index 000000000..db66f86df --- /dev/null +++ b/src/tv2-common/pieces/telemetric.ts @@ -0,0 +1,40 @@ +import { IBlueprintPiece, PieceLifespan, TSR } from 'blueprints-integration' +import { RobotCameraLayer, SharedOutputLayers, SharedSourceLayers } from '../../tv2-constants' +import { literal } from '../util' + +export const ROBOT_CAMERA_NAME_PREFIX: string = 'Robot' + +export function createTelemetricsPieceForRobotCamera( + externalId: string, + preset: number, + startTime: number | 'now' +): IBlueprintPiece { + return { + externalId, + name: `${ROBOT_CAMERA_NAME_PREFIX}[${preset}]`, + enable: { + start: startTime, + duration: 100 + }, + lifespan: PieceLifespan.WithinPart, + sourceLayerId: SharedSourceLayers.RobotCamera, + outputLayerId: SharedOutputLayers.SEC, + content: { + timelineObjects: [createTelemetricsTimelineObject(preset)] + } + } +} + +function createTelemetricsTimelineObject(preset: number): TSR.TimelineObjTelemetrics { + return literal({ + id: `telemetrics_preset_${preset}_${Math.random() * 1000}`, + enable: { + start: 0 + }, + layer: RobotCameraLayer.TELEMETRICS, + content: { + deviceType: TSR.DeviceType.TELEMETRICS, + presetShotIdentifiers: [preset] + } + }) +} diff --git a/src/tv2-common/showstyle/config-manifests.ts b/src/tv2-common/showstyle/config-manifests.ts new file mode 100644 index 000000000..bdfd4a826 --- /dev/null +++ b/src/tv2-common/showstyle/config-manifests.ts @@ -0,0 +1,49 @@ +import { ConfigManifestEntry, ConfigManifestEntryTable, ConfigManifestEntryType } from 'blueprints-integration' + +export const GRAPHICS_SETUPS_TABLE_ID = 'GraphicsSetups' +export const GRAPHICS_SETUPS_NAME_COLUMN_ID = 'Name' + +export const getGraphicsSetupsEntries = (columns: ConfigManifestEntryTable['columns']): ConfigManifestEntry[] => [ + { + id: GRAPHICS_SETUPS_TABLE_ID, + name: 'Graphics Setups', + description: 'Possible graphics setups', + type: ConfigManifestEntryType.TABLE, + required: false, + defaultVal: [], + columns: [ + { + id: 'Name', + name: 'Name', + description: 'The code as it will appear in iNews', + type: ConfigManifestEntryType.STRING, + required: true, + defaultVal: '', + rank: 0 + }, + { + id: 'HtmlPackageFolder', + name: 'HTML Package Folder', + rank: 4, + required: true, + defaultVal: '', + description: + 'Name of the folder containing the HTML graphics template package, relative to the template-path in CasparCG, e.g. sport-overlay', + type: ConfigManifestEntryType.STRING + }, + ...columns + ], + hint: '' + }, + { + id: 'SelectedGraphicsSetupName', + name: 'Graphic Setup name', + description: 'Name of the Graphic Setup that should be used', + type: ConfigManifestEntryType.SELECT_FROM_COLUMN, + tableId: GRAPHICS_SETUPS_TABLE_ID, + columnId: GRAPHICS_SETUPS_NAME_COLUMN_ID, + multiple: false, + required: false, + defaultVal: '' + } +] diff --git a/src/tv2-common/sources.ts b/src/tv2-common/sources.ts index a3f0f6615..14fde8d0e 100644 --- a/src/tv2-common/sources.ts +++ b/src/tv2-common/sources.ts @@ -1,6 +1,6 @@ import * as _ from 'underscore' -import { IStudioContext, SourceLayerType } from '@tv2media/blueprints-integration' +import { IStudioContext, SourceLayerType } from 'blueprints-integration' import { SourceType } from 'tv2-constants' import { SourceMapping } from './blueprintConfig' import { diff --git a/src/tv2-common/transitionSettings.ts b/src/tv2-common/transitionSettings.ts index 03ea8e525..1c87ec2f1 100644 --- a/src/tv2-common/transitionSettings.ts +++ b/src/tv2-common/transitionSettings.ts @@ -1,4 +1,4 @@ -import { TSR } from '@tv2media/blueprints-integration' +import { TSR } from 'blueprints-integration' import { PartDefinition, TV2BlueprintConfig } from 'tv2-common' import { AtemSourceIndex } from '../types/atem' diff --git a/src/tv2-common/translateEngine.ts b/src/tv2-common/translateEngine.ts deleted file mode 100644 index fde939752..000000000 --- a/src/tv2-common/translateEngine.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { GraphicEngine } from 'tv2-constants' - -export function TranslateEngine(eng: string): GraphicEngine { - return !!eng.match(/WALL/i) ? 'WALL' : !!eng.match(/FULL/i) ? 'FULL' : 'OVL' -} diff --git a/src/tv2-common/updatePolicies/adlibs.ts b/src/tv2-common/updatePolicies/adlibs.ts index 241113ee7..7467c0052 100644 --- a/src/tv2-common/updatePolicies/adlibs.ts +++ b/src/tv2-common/updatePolicies/adlibs.ts @@ -2,7 +2,7 @@ import { BlueprintSyncIngestNewData, BlueprintSyncIngestPartInstance, ISyncIngestUpdateToPartInstanceContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { PieceMetaData } from 'tv2-common' import _ = require('underscore') diff --git a/src/tv2-common/updatePolicies/index.ts b/src/tv2-common/updatePolicies/index.ts index bd67aa402..d05055083 100644 --- a/src/tv2-common/updatePolicies/index.ts +++ b/src/tv2-common/updatePolicies/index.ts @@ -2,4 +2,3 @@ export * from './adlibs' export * from './partProperties' export * from './pieces' export * from './syncIngestUpdateToPartInstance' -export * from './shouldRemoveOrphanedPartInstance' diff --git a/src/tv2-common/updatePolicies/partProperties.ts b/src/tv2-common/updatePolicies/partProperties.ts index eb5277864..3432a161a 100644 --- a/src/tv2-common/updatePolicies/partProperties.ts +++ b/src/tv2-common/updatePolicies/partProperties.ts @@ -3,7 +3,7 @@ import { BlueprintSyncIngestPartInstance, IBlueprintMutatablePart, ISyncIngestUpdateToPartInstanceContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import _ = require('underscore') type Complete = { diff --git a/src/tv2-common/updatePolicies/pieces.ts b/src/tv2-common/updatePolicies/pieces.ts index ed96c3bdc..30e9bc31f 100644 --- a/src/tv2-common/updatePolicies/pieces.ts +++ b/src/tv2-common/updatePolicies/pieces.ts @@ -3,7 +3,7 @@ import { BlueprintSyncIngestPartInstance, IBlueprintPieceInstance, ISyncIngestUpdateToPartInstanceContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' function groupPieceInstances(pieceInstances: Array>) { return pieceInstances.reduce<{ diff --git a/src/tv2-common/updatePolicies/shouldRemoveOrphanedPartInstance.ts b/src/tv2-common/updatePolicies/shouldRemoveOrphanedPartInstance.ts deleted file mode 100644 index 626c4a5a1..000000000 --- a/src/tv2-common/updatePolicies/shouldRemoveOrphanedPartInstance.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { BlueprintRemoveOrphanedPartInstance, IRundownUserContext } from '@tv2media/blueprints-integration' -import { PartMetaData } from 'tv2-common' - -export function shouldRemoveOrphanedPartInstance( - _context: IRundownUserContext, - partInstance: BlueprintRemoveOrphanedPartInstance -): boolean { - 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 c385a68fc..258c5bc7f 100644 --- a/src/tv2-common/updatePolicies/syncIngestUpdateToPartInstance.ts +++ b/src/tv2-common/updatePolicies/syncIngestUpdateToPartInstance.ts @@ -2,7 +2,7 @@ import { BlueprintSyncIngestNewData, BlueprintSyncIngestPartInstance, ISyncIngestUpdateToPartInstanceContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { SharedSourceLayers } from 'tv2-constants' import * as _ from 'underscore' import { stopOrReplaceEditablePieces, updateAdLibInstances } from './index' diff --git a/src/tv2-common/util.ts b/src/tv2-common/util.ts index 39f213903..129c4feac 100644 --- a/src/tv2-common/util.ts +++ b/src/tv2-common/util.ts @@ -1,4 +1,4 @@ -import { IBlueprintAdLibPiece, IBlueprintPiece, ICommonContext, TSR } from '@tv2media/blueprints-integration' +import { IBlueprintAdLibPiece, IBlueprintPiece, ICommonContext, TSR } from 'blueprints-integration' import { ActionBase } from './actions' export function literal(o: T) { @@ -36,7 +36,7 @@ export function SanitizeString(str: string) { return str.replace(/\W/g, '_') } -export function JoinAssetToFolder(folder: string | undefined, assetFile: string) { +export function joinAssetToFolder(folder: string | undefined, assetFile: string) { if (!folder) { return assetFile } @@ -52,7 +52,7 @@ export function JoinAssetToFolder(folder: string | undefined, assetFile: string) return `${folderWithoutTrailingSlashes}/${assetFileWithoutLeadingSlashes}` } -export function JoinAssetToNetworkPath( +export function joinAssetToNetworkPath( networkPath: string, folder: string | undefined, assetFile: string, diff --git a/src/tv2-constants/enums.ts b/src/tv2-constants/enums.ts index d7f0f6605..fcbb47084 100644 --- a/src/tv2-constants/enums.ts +++ b/src/tv2-constants/enums.ts @@ -32,7 +32,8 @@ export enum CueType { Graphic, Routing, PgmClean, - MixMinus + MixMinus, + RobotCamera } export const enum PartType { @@ -104,6 +105,7 @@ export enum AdlibTags { ADLIB_RECALL_LAST_DVE = 'recall_last_dve', ADLIB_SELECT_DVE_LAYOUT = 'select_dve_layout', ADLIB_TAKE_WITH_TRANSITION = 'take_with_transition', + ADLIB_NEXT_TAKE_WITH_TRANSITION = 'next_take_with_transition', ADLIB_FADE_DOWN_PERSISTED_AUDIO_LEVELS = 'fade_down_persisted_audio_levels' } @@ -147,7 +149,8 @@ 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' + FADE_DOWN_PERSISTED_AUDIO_LEVELS = 'fade_down_persisted_audio_levels', + CALL_ROBOT_PRESET = 'call_robot_preset' } export enum TallyTags { @@ -178,8 +181,8 @@ export enum SharedGraphicLLayer { GraphicLLayerOverlayLower = 'graphic_overlay_lower', // <= viz_layer_overlay_lower GraphicLLayerOverlayHeadline = 'graphic_overlay_headline', // <= viz_layer_overlay_headline GraphicLLayerOverlayTema = 'graphic_overlay_tema', // <= viz_layer_overlay_tema + GraphicLLayerOverlayPilot = 'graphic_overlay_pilot', // <= viz_layer_pilot_overlay GraphicLLayerPilot = 'graphic_pilot', // <= viz_layer_pilot - GraphicLLayerPilotOverlay = 'graphic_pilot_overlay', // <= viz_layer_pilot_overlay GraphicLLayerDesign = 'graphic_design', // <= viz_layer_design GraphicLLayerFullLoop = 'graphic_full_loop', GraphicLLayerAdLibs = 'graphic_adlibs', // <= viz_layer_adlibs @@ -211,6 +214,10 @@ export enum SharedSisyfosLLayer { SisyfosGroupStudioMics = 'sisyfos_group_studio_mics' } +export enum RobotCameraLayer { + TELEMETRICS = 'telemetrics_layer' +} + export enum SharedOutputLayers { OVERLAY = 'overlay', SEC = 'sec', @@ -263,7 +270,9 @@ export enum SharedSourceLayers { PgmAudioBed = 'studio0_audio_bed', // AUX - AuxMixMinus = 'studio0_aux_mix_minus' + AuxMixMinus = 'studio0_aux_mix_minus', + + RobotCamera = 'studio0_robot_camera' } export enum DSKRoles { diff --git a/src/tv2_afvd_showstyle/__tests__/actions.spec.ts b/src/tv2_afvd_showstyle/__tests__/actions.spec.ts index b84748084..c27aec8a5 100644 --- a/src/tv2_afvd_showstyle/__tests__/actions.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/actions.spec.ts @@ -6,7 +6,7 @@ import { IBlueprintPieceInstance, PieceLifespan, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionCutToCamera, ActionTakeWithTransition, literal, SourceDefinitionKam } from 'tv2-common' import { AdlibActionType, NoteType, SharedOutputLayers, SourceType } from 'tv2-constants' import { ActionExecutionContext } from '../../__mocks__/context' diff --git a/src/tv2_afvd_showstyle/__tests__/addScript.spec.ts b/src/tv2_afvd_showstyle/__tests__/addScript.spec.ts index 37d317676..160a6bb7e 100644 --- a/src/tv2_afvd_showstyle/__tests__/addScript.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/addScript.spec.ts @@ -1,4 +1,4 @@ -import { IBlueprintPiece, PieceLifespan, ScriptContent, WithTimeline } from '@tv2media/blueprints-integration' +import { IBlueprintPiece, PieceLifespan, ScriptContent, WithTimeline } from 'blueprints-integration' import { AddScript, literal, PartDefinitionKam } from 'tv2-common' import { PartType, SharedOutputLayers, SourceType } from 'tv2-constants' import { SourceLayer } from '../layers' diff --git a/src/tv2_afvd_showstyle/__tests__/baseline.spec.ts b/src/tv2_afvd_showstyle/__tests__/baseline.spec.ts index 48f483953..9cdf57a24 100644 --- a/src/tv2_afvd_showstyle/__tests__/baseline.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/baseline.spec.ts @@ -7,7 +7,7 @@ global.VERSION_TSR = 'test' // @ts-ignore global.VERSION_INTEGRATION = 'test' -import { ExtendedIngestRundown, IGetRundownContext, TSR } from '@tv2media/blueprints-integration' +import { ExtendedIngestRundown, IGetRundownContext, TSR } from 'blueprints-integration' import { GetRundownContext } from '../../__mocks__/context' import { SharedGraphicLLayer } from '../../tv2-constants' import { parseConfig as parseStudioConfig } from '../../tv2_afvd_studio/helpers/config' diff --git a/src/tv2_afvd_showstyle/__tests__/blueprint.spec.ts b/src/tv2_afvd_showstyle/__tests__/blueprint.spec.ts index acce40bf4..a517fa91a 100644 --- a/src/tv2_afvd_showstyle/__tests__/blueprint.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/blueprint.spec.ts @@ -1,8 +1,4 @@ -import { - BlueprintResultSegment, - IBlueprintActionManifestDisplayContent, - IngestSegment -} from '@tv2media/blueprints-integration' +import { BlueprintResultSegment, IBlueprintActionManifestDisplayContent, IngestSegment } from 'blueprints-integration' import { INewsStory, literal, UnparsedCue } from 'tv2-common' import { SharedSourceLayers } from 'tv2-constants' import { makeMockAFVDContext, SegmentUserContext } from '../../__mocks__/context' @@ -731,7 +727,7 @@ describe('AFVD Blueprint', () => { it('Changes design and background loops', async () => { const ingestSegment = makeIngestSegment( [ - ['KG=DESIGN_FODBOLD_20', ';0.00.01'], + ['KG=DESIGN_FODBOLD_22', ';0.00.01'], ['VIZ=dve-triopage', 'GRAFIK=BG_LOADER_FODBOLD_20', ';0.00'], ['VIZ=full-triopage', 'GRAFIK=BG_LOADER_FODBOLD_20', ';0.00.01'] ], diff --git a/src/tv2_afvd_showstyle/__tests__/config-manifest.spec.ts b/src/tv2_afvd_showstyle/__tests__/config-manifest.spec.ts index 9e7358d75..b068654ff 100644 --- a/src/tv2_afvd_showstyle/__tests__/config-manifest.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/config-manifest.spec.ts @@ -6,6 +6,7 @@ const blankShowStyleConfig: ShowStyleConfig = { MakeAdlibsForFulls: true, DVEStyles: [], GFXTemplates: [], + GfxDesignTemplates: [], WipesConfig: [], BreakerConfig: [], DefaultTemplateDuration: 4, @@ -15,7 +16,8 @@ const blankShowStyleConfig: ShowStyleConfig = { ShowstyleTransition: 'CUT', SelectedGraphicsSetupName: '', GraphicsSetups: [], - SchemaConfig: [] + GfxSchemaTemplates: [], + OverlayShowMapping: [] } describe('Config Manifest', () => { diff --git a/src/tv2_afvd_showstyle/__tests__/configs.ts b/src/tv2_afvd_showstyle/__tests__/configs.ts index a073fb317..a2b9525d6 100644 --- a/src/tv2_afvd_showstyle/__tests__/configs.ts +++ b/src/tv2_afvd_showstyle/__tests__/configs.ts @@ -1,6 +1,6 @@ -import { literal, parseMapStr, TableConfigGraphicsSetup } from 'tv2-common' +import { literal, parseMapStr } from 'tv2-common' import { defaultDSKConfig, StudioConfig } from '../../tv2_afvd_studio/helpers/config' -import { ShowStyleConfig } from '../helpers/config' +import { GalleryTableConfigGraphicsSetup, ShowStyleConfig } from '../helpers/config' import { DefaultBreakerConfig } from './breakerConfigDefault' import { DefaultGrafikConfig } from './grafikConfigDefault' @@ -42,14 +42,14 @@ function prepareConfig( }) } -export const OVL_SHOW_ID = 'ovl-show-id' -export const FULL_SHOW_ID = 'full-show-id' -export const DEFAULT_GRAPHICS_SETUP: TableConfigGraphicsSetup = { +export const OVL_SHOW_NAME = 'ovl-show-id' +export const FULL_SHOW_NAME = 'full-show-id' +export const DEFAULT_GRAPHICS_SETUP: GalleryTableConfigGraphicsSetup = { Name: 'SomeProfile', VcpConcept: 'SomeConcept', - OvlShowId: OVL_SHOW_ID, - FullShowId: FULL_SHOW_ID, - DveLayoutFolder: 'folder/path' + OvlShowName: OVL_SHOW_NAME, + FullShowName: FULL_SHOW_NAME, + HtmlPackageFolder: 'html-package-folder' } // in here will be some mock configs that can be referenced paired with ro's for the tests @@ -65,12 +65,12 @@ export const defaultStudioConfig: StudioConfig = { AudioBedFileExtension: '.wav', DVEFileExtension: '.png', ClipNetworkBasePath: '/', - GraphicNetworkBasePath: '/', + GraphicNetworkBasePath: 'networkshare/somefolder', JingleNetworkBasePath: '/', AudioBedNetworkBasePath: '/', DVENetworkBasePath: '/', ClipFolder: '', - GraphicFolder: '', + GraphicFolder: 'pilot-images', JingleFolder: '', AudioBedFolder: '', DVEFolder: '', @@ -137,7 +137,7 @@ export const defaultStudioConfig: StudioConfig = { FullGraphicBackground: 36 }, HTMLGraphics: { - GraphicURL: '', + GraphicURL: 'E:/somepath', KeepAliveDuration: 1000, TransitionSettings: { wipeRate: 20, @@ -195,7 +195,6 @@ export const defaultShowStyleConfig: ShowStyleConfig = { VizTemplate: 'VCP', VizDestination: 'WALL1', OutType: 'O', - IsDesign: false, SourceLayer: 'studio0_wall_graphics', LayerMapping: 'graphic_wall' }, @@ -205,7 +204,6 @@ export const defaultShowStyleConfig: ShowStyleConfig = { VizTemplate: 'VCP', VizDestination: 'OVL1', OutType: 'O', - IsDesign: false, SourceLayer: 'studio0_overlay', LayerMapping: 'graphic_overlay' }, @@ -215,7 +213,6 @@ export const defaultShowStyleConfig: ShowStyleConfig = { VizTemplate: 'VCP', VizDestination: 'OVL1', OutType: 'O', - IsDesign: false, SourceLayer: 'studio0_overlay', LayerMapping: 'graphic_overlay' }, @@ -225,12 +222,18 @@ export const defaultShowStyleConfig: ShowStyleConfig = { VizTemplate: 'tlftoptlive', VizDestination: 'OVL1', OutType: 'S', - IsDesign: false, SourceLayer: 'studio0_graphicsTop', LayerMapping: 'graphic_overlay_topt' } ]) ], + GfxDesignTemplates: [ + { + INewsName: 'DESIGN_FODBOLD_22', + INewsStyleColumn: '', + VizTemplate: 'DESIGN_FODBOLD_22' + } + ], LYDConfig: [ { _id: '', @@ -268,7 +271,8 @@ export const defaultShowStyleConfig: ShowStyleConfig = { GraphicsSetups: [DEFAULT_GRAPHICS_SETUP], Transitions: [{ Transition: '1' }, { Transition: '2' }], ShowstyleTransition: 'CUT', - SchemaConfig: [] + GfxSchemaTemplates: [], + OverlayShowMapping: [] } export const EMPTY_SOURCE_CONFIG = { diff --git a/src/tv2_afvd_showstyle/__tests__/layers-check.ts b/src/tv2_afvd_showstyle/__tests__/layers-check.ts index 7b99f7217..1413a70af 100644 --- a/src/tv2_afvd_showstyle/__tests__/layers-check.ts +++ b/src/tv2_afvd_showstyle/__tests__/layers-check.ts @@ -6,7 +6,7 @@ import { IShowStyleUserContext, TimelineObjectCoreExt, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { GetDSKSourceLayerNames } from 'tv2-common' import mappingsDefaults, { getMediaPlayerMappings } from '../../tv2_afvd_studio/migrations/mappings-defaults' diff --git a/src/tv2_afvd_showstyle/__tests__/regressions.spec.ts b/src/tv2_afvd_showstyle/__tests__/regressions.spec.ts index 5178d61e8..0f5b291bc 100644 --- a/src/tv2_afvd_showstyle/__tests__/regressions.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/regressions.spec.ts @@ -1,6 +1,6 @@ import * as _ from 'underscore' -import { BlueprintResultSegment, PieceLifespan, TimelineObjectCoreExt } from '@tv2media/blueprints-integration' +import { BlueprintResultSegment, PieceLifespan, TimelineObjectCoreExt } from 'blueprints-integration' // @ts-ignore global.VERSION = 'test' diff --git a/src/tv2_afvd_showstyle/__tests__/rundown_story_exception.spec.ts b/src/tv2_afvd_showstyle/__tests__/rundown_story_exception.spec.ts index 92c4abbdb..6f89f7f8b 100644 --- a/src/tv2_afvd_showstyle/__tests__/rundown_story_exception.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/rundown_story_exception.spec.ts @@ -1,6 +1,6 @@ import * as _ from 'underscore' -import { ExtendedIngestRundown, IBlueprintPieceGeneric } from '@tv2media/blueprints-integration' +import { ExtendedIngestRundown, IBlueprintPieceGeneric } from 'blueprints-integration' import { defaultShowStyleConfig, defaultStudioConfig } from './configs' import { checkAllLayers } from './layers-check' diff --git a/src/tv2_afvd_showstyle/__tests__/syncIngestChangesToPartInstance.spec.ts b/src/tv2_afvd_showstyle/__tests__/syncIngestChangesToPartInstance.spec.ts index 5264bd907..5c709431d 100644 --- a/src/tv2_afvd_showstyle/__tests__/syncIngestChangesToPartInstance.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/syncIngestChangesToPartInstance.spec.ts @@ -7,7 +7,7 @@ import { IBlueprintRundownDB, PieceLifespan, PlaylistTimingType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' import { SyncIngestUpdateToPartInstanceContext } from '../../__mocks__/context' @@ -189,7 +189,7 @@ describe('Sync Ingest Changes To Part Instances', () => { makeSoundBed('someId4', 'SN_Intro', { infinite: { infinitePieceId: 'someInfinite', fromPreviousPart: false, fromHold: true } }), - makeSoundBed('someId5', 'SN_Intro', { dynamicallyInserted: 1649158767173 }) + makeSoundBed('someId5', 'SN_Intro', { dynamicallyInserted: { time: 1649158767173 } }) ] }) const newPart: BlueprintSyncIngestNewData = literal({ diff --git a/src/tv2_afvd_showstyle/__tests__/transitions.spec.ts b/src/tv2_afvd_showstyle/__tests__/transitions.spec.ts index a8097cee3..a18fe9716 100644 --- a/src/tv2_afvd_showstyle/__tests__/transitions.spec.ts +++ b/src/tv2_afvd_showstyle/__tests__/transitions.spec.ts @@ -1,11 +1,5 @@ -import { - BlueprintResultSegment, - IBlueprintPart, - IBlueprintPiece, - IngestSegment, - TSR -} from '@tv2media/blueprints-integration' import { fail } from 'assert' +import { BlueprintResultSegment, IBlueprintPart, IBlueprintPiece, IngestSegment, TSR } from 'blueprints-integration' import { TimeFromFrames } from 'tv2-common' import * as _ from 'underscore' import { SegmentUserContext } from '../../__mocks__/context' diff --git a/src/tv2_afvd_showstyle/actions.ts b/src/tv2_afvd_showstyle/actions.ts index beebb70f6..4da99a841 100644 --- a/src/tv2_afvd_showstyle/actions.ts +++ b/src/tv2_afvd_showstyle/actions.ts @@ -1,4 +1,4 @@ -import { ActionUserData, IActionExecutionContext } from '@tv2media/blueprints-integration' +import { ActionUserData, IActionExecutionContext } from 'blueprints-integration' import { executeAction } from 'tv2-common' import { AtemLLayer, CasparLLayer, SisyfosLLAyer } from '../tv2_afvd_studio/layers' import { getConfig } from './helpers/config' diff --git a/src/tv2_afvd_showstyle/config-manifests.ts b/src/tv2_afvd_showstyle/config-manifests.ts index 259a7c995..b4176be5d 100644 --- a/src/tv2_afvd_showstyle/config-manifests.ts +++ b/src/tv2_afvd_showstyle/config-manifests.ts @@ -1,5 +1,10 @@ -import { ConfigManifestEntry, ConfigManifestEntryType, TSR } from '@tv2media/blueprints-integration' -import { DEFAULT_GRAPHICS } from 'tv2-common' +import { ConfigManifestEntry, ConfigManifestEntryType, TSR } from 'blueprints-integration' +import { + DEFAULT_GRAPHICS, + getGraphicsSetupsEntries, + GRAPHICS_SETUPS_NAME_COLUMN_ID, + GRAPHICS_SETUPS_TABLE_ID +} from 'tv2-common' export const dveStylesManifest: ConfigManifestEntry = { id: 'DVEStyles', @@ -142,126 +147,172 @@ export const dveStylesManifest: ConfigManifestEntry = { ] } -const graphicsSetups: ConfigManifestEntry[] = [ +const graphicsSetups = getGraphicsSetupsEntries([ { - id: 'GraphicsSetups', - name: 'Graphics Setups', - description: 'Possible graphics setups', + id: 'VcpConcept', + name: 'VCP Concept', + rank: 1, + required: true, + defaultVal: '', + hint: '', + description: '', + type: ConfigManifestEntryType.STRING + }, + { + id: 'OvlShowName', + name: 'Overlay Show Name', + rank: 2, + required: true, + defaultVal: '', + hint: '', + description: 'Name of the show used for OVL channel', + type: ConfigManifestEntryType.STRING + }, + { + id: 'FullShowName', + name: 'Fullscreen Show Name', + rank: 3, + required: true, + defaultVal: '', + hint: '', + description: 'Name of the show used for FULL and WALL channels', + type: ConfigManifestEntryType.STRING + } +]) + +const DESIGN_TABLE_ID = 'GfxDesignTemplates' +const DESIGN_NAME_COLUMN_ID = 'INewsName' + +export const gfxDesignTemplates: ConfigManifestEntry[] = [ + { + id: DESIGN_TABLE_ID, + name: 'GFX Design Templates', + description: '', type: ConfigManifestEntryType.TABLE, - required: false, - defaultVal: [], + required: true, + defaultVal: DEFAULT_GRAPHICS.map(val => ({ _id: '', ...val })).filter(template => template.IsDesign), columns: [ { - id: 'Name', - name: 'Name', - description: 'The code as it will appear in iNews', + id: DESIGN_NAME_COLUMN_ID, + name: 'iNews Name', + description: 'The name of the design', type: ConfigManifestEntryType.STRING, - required: true, + required: false, defaultVal: '', rank: 0 }, { - id: 'VcpConcept', - name: 'VCP Concept', - rank: 1, - required: true, - defaultVal: '', - hint: '', - description: '', - type: ConfigManifestEntryType.STRING - }, - { - id: 'OvlShowId', - name: 'Overlay Show-ID', - rank: 2, - required: true, - defaultVal: '', - hint: '', - description: 'UUID of the show used for OVL channel', - type: ConfigManifestEntryType.STRING - }, - { - id: 'FullShowId', - name: 'Fullscreen Show-ID', - rank: 3, - required: true, + id: 'INewsStyleColumn', + name: 'iNews Style Column', + description: 'The selected style', + type: ConfigManifestEntryType.STRING, + required: false, defaultVal: '', - hint: '', - description: 'UUID of the show used for FULL and WALL channels', - type: ConfigManifestEntryType.STRING + rank: 1 }, { - id: 'DveLayoutFolder', - name: 'DVE layout folder', - rank: 4, + id: 'VizTemplate', + name: 'GFX Template Name', + description: 'The name of the Viz Template', + type: ConfigManifestEntryType.STRING, required: true, defaultVal: '', - hint: '', - description: 'Path to the folder containing the layouts for DVEs', - type: ConfigManifestEntryType.STRING + rank: 2 } - ], - hint: '' - }, - { - id: 'SelectedGraphicsSetupName', - name: 'Graphic Setup name', - description: 'Name of the Graphic Setup that should be used', - type: ConfigManifestEntryType.STRING, - required: false, - defaultVal: '' + ] } ] -export const schemaConfigManifest: ConfigManifestEntry[] = [ +const GFX_SCHEMA_TABLE_ID = 'GfxSchemaTemplates' +const GFX_SCHEMA_NAME_COLUMN_ID = 'GfxSchemaTemplatesName' + +export const gfxSchemaTemplates: ConfigManifestEntry[] = [ { - id: 'SchemaConfig', - name: 'Skema', + id: GFX_SCHEMA_TABLE_ID, + name: 'GFX Skema Templates', description: 'The values for the Skema and Design combinations', type: ConfigManifestEntryType.TABLE, required: false, defaultVal: [], columns: [ { - id: 'schemaName', - name: 'Skema', - description: 'The name of the Skema', - rank: 0, - required: true, + id: GFX_SCHEMA_NAME_COLUMN_ID, + name: 'iNews Name', + description: 'The name of the design', + type: ConfigManifestEntryType.STRING, + required: false, defaultVal: '', - type: ConfigManifestEntryType.STRING + rank: 0 }, { - id: 'designIdentifier', - name: 'Design', - description: 'The identifier of the Design', - rank: 1, - required: true, + id: 'INewsSkemaColumn', + name: 'iNews Skema Column', + description: 'The selected skema', + type: ConfigManifestEntryType.STRING, + required: false, defaultVal: '', - type: ConfigManifestEntryType.STRING + rank: 1 }, { - id: 'vizTemplateName', - name: 'Viz Template Name', - description: 'The name of the Viz template', - rank: 2, + id: 'VizTemplate', + name: 'GFX Template Name', + description: 'The name of the Viz Template', + type: ConfigManifestEntryType.STRING, required: true, defaultVal: '', - type: ConfigManifestEntryType.STRING - }, - { - id: 'casparCgDveBgScene', - name: 'CasparCG DVE Bg Scene', - description: 'The dveBgScene', - defaultVal: '', - rank: 3, - required: true, - type: ConfigManifestEntryType.STRING + rank: 2 } ] } ] +export const overlayShowMapping: ConfigManifestEntry = { + id: 'OverlayShowMapping', + name: 'Overlay Show mapping', + description: 'Maps Overlay Shows to the variety of Skemas and Designs', + type: ConfigManifestEntryType.TABLE, + required: false, + defaultVal: [], + columns: [ + { + id: 'Design', + name: 'Design', + rank: 0, + description: 'Name of the Design from the GFX Design table', + type: ConfigManifestEntryType.SELECT_FROM_COLUMN, + tableId: DESIGN_TABLE_ID, + columnId: DESIGN_NAME_COLUMN_ID, + multiple: false, + required: false, + defaultVal: '' + }, + { + id: 'GraphicsSetup', + name: 'Graphics Setup', + rank: 1, + description: 'Names of the Graphics Setups', + type: ConfigManifestEntryType.SELECT_FROM_COLUMN, + tableId: GRAPHICS_SETUPS_TABLE_ID, + columnId: GRAPHICS_SETUPS_NAME_COLUMN_ID, + multiple: true, + required: false, + defaultVal: [] + }, + { + id: 'Schema', + name: 'GFX Skema Templates', + rank: 2, + description: 'Names of the Skemas', + type: ConfigManifestEntryType.SELECT_FROM_COLUMN, + tableId: GFX_SCHEMA_TABLE_ID, + columnId: GFX_SCHEMA_NAME_COLUMN_ID, + multiple: true, + required: false, + defaultVal: [] + } + ] +} + export const showStyleConfigManifest: ConfigManifestEntry[] = [ { id: 'MakeAdlibsForFulls', @@ -296,10 +347,10 @@ export const showStyleConfigManifest: ConfigManifestEntry[] = [ id: 'GFXTemplates', name: 'GFX Templates', description: - 'This table can contain info in two ways. Things marked (**) are always required. If you want to do the mapping from iNews-code, then all (*)-elements are aslo required. VizTemplate is what the graphic is called in viz. Source layer is the ID of the Sofie Source layer in the UI (i.e. "studio0_graphicsTema"). Layer mapping is the Sofie studio layer mapping (i.e "viz_layer_tema"). iNews command can be something like "KG=", then iNews Name is the thing that follows in iNes i.e. "ident_nyhederne"', + 'This table can contain info in two ways. Things marked (**) are always required. If you want to do the mapping from iNews-code, then all (*)-elements are also required. GFX Template Name is what the graphic is called in viz. Source layer is the ID of the Sofie Source layer in the UI (i.e. "studio0_graphicsTema"). Layer mapping is the Sofie studio layer mapping (i.e "viz_layer_tema"). iNews command can be something like "KG=", then iNews Name is the thing that follows in iNews i.e. "ident_nyhederne"', type: ConfigManifestEntryType.TABLE, required: true, - defaultVal: DEFAULT_GRAPHICS.map(val => ({ _id: '', ...val })), + defaultVal: DEFAULT_GRAPHICS.map(val => ({ _id: '', ...val })).filter(template => !template.IsDesign), columns: [ { id: 'INewsCode', @@ -321,7 +372,7 @@ export const showStyleConfigManifest: ConfigManifestEntry[] = [ }, { id: 'VizTemplate', - name: 'Viz Template Name (**)', + name: 'GFX Template Name (**)', description: 'The name of the Viz Template', type: ConfigManifestEntryType.STRING, required: true, @@ -348,15 +399,6 @@ export const showStyleConfigManifest: ConfigManifestEntry[] = [ defaultVal: '', rank: 4 }, - { - id: 'IsDesign', - name: 'Changes Design', - description: 'Whether this cue changes the design', - type: ConfigManifestEntryType.BOOLEAN, - required: false, - defaultVal: false, - rank: 5 - }, { id: 'SourceLayer', name: 'Source layer (**)', @@ -383,8 +425,10 @@ export const showStyleConfigManifest: ConfigManifestEntry[] = [ } ] }, + ...gfxDesignTemplates, ...graphicsSetups, - ...schemaConfigManifest, + ...gfxSchemaTemplates, + overlayShowMapping, { /* Wipes Config diff --git a/src/tv2_afvd_showstyle/getRundown.ts b/src/tv2_afvd_showstyle/getRundown.ts index cb605c4df..631a873cc 100644 --- a/src/tv2_afvd_showstyle/getRundown.ts +++ b/src/tv2_afvd_showstyle/getRundown.ts @@ -4,6 +4,7 @@ import { GraphicsContent, IBlueprintActionManifest, IBlueprintAdLibPiece, + ICommonContext, IngestRundown, IShowStyleUserContext, IStudioUserContext, @@ -12,8 +13,9 @@ import { TimelineObjectCoreExt, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { + ActionCallRobotPreset, ActionClearGraphics, ActionCutSourceToBox, ActionCutToCamera, @@ -110,8 +112,7 @@ function getGlobalAdLibPiecesAFVD(context: IStudioUserContext, config: Blueprint input: info.port, transition: TSR.AtemTransitionStyle.CUT } - }, - classes: ['adlib_deparent'] + } }), ...GetSisyfosTimelineObjForReplay(config, info, vo) ] @@ -154,8 +155,7 @@ function getGlobalAdLibPiecesAFVD(context: IStudioUserContext, config: Blueprint input: info.port, transition: TSR.AtemTransitionStyle.CUT } - }, - classes: ['adlib_deparent'] + } }), ...eksternSisyfos ] @@ -459,7 +459,7 @@ function getGlobalAdLibPiecesAFVD(context: IStudioUserContext, config: Blueprint type: TSR.TimelineContentTypeVizMSE.ELEMENT_INTERNAL, templateName: 'BG_LOADER_SC', templateData: [], - showId: config.selectedGraphicsSetup.OvlShowId + showId: config.selectedGraphicsSetup.OvlShowName } }) ) @@ -795,9 +795,30 @@ function getGlobalAdlibActionsAFVD(_context: IStudioUserContext, config: Bluepri } }) + blueprintActions.push(createRobotPresetAction(_context)) + return blueprintActions } +function createRobotPresetAction(context: ICommonContext): IBlueprintActionManifest { + const callRobotPresetAction: ActionCallRobotPreset = { + type: AdlibActionType.CALL_ROBOT_PRESET + } + return { + externalId: generateExternalId(context, callRobotPresetAction), + actionId: AdlibActionType.CALL_ROBOT_PRESET, + userData: callRobotPresetAction, + userDataManifest: {}, + display: { + _rank: 400, + label: t(`Call Robot preset`), + sourceLayerId: SourceLayer.RobotCamera, + outputLayerId: SharedOutputLayers.SEC, + tags: [] + } + } +} + function getBaseline(config: BlueprintConfig): BlueprintResultBaseline { const jingleDSK = FindDSKJingle(config) diff --git a/src/tv2_afvd_showstyle/getSegment.ts b/src/tv2_afvd_showstyle/getSegment.ts index bb910eedc..e7bf2a4b2 100644 --- a/src/tv2_afvd_showstyle/getSegment.ts +++ b/src/tv2_afvd_showstyle/getSegment.ts @@ -8,7 +8,7 @@ import { PieceLifespan, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { getSegmentBase, INewsPayload, literal } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' import * as _ from 'underscore' @@ -124,11 +124,11 @@ function insertSpecialPieces( const showsToInitialize = new Set() const allShows = new Set() config.showStyle.GraphicsSetups.forEach(graphicsSetup => { - allShows.add(graphicsSetup.FullShowId) - allShows.add(graphicsSetup.OvlShowId) + allShows.add(graphicsSetup.FullShowName) + allShows.add(graphicsSetup.OvlShowName) if (graphicsSetupsToInitialize.includes(graphicsSetup.Name)) { - showsToInitialize.add(graphicsSetup.FullShowId) - showsToInitialize.add(graphicsSetup.OvlShowId) + showsToInitialize.add(graphicsSetup.FullShowName) + showsToInitialize.add(graphicsSetup.OvlShowName) } }) const showsToCleanup = Array.from(allShows).filter(show => !showsToInitialize.has(show)) diff --git a/src/tv2_afvd_showstyle/helpers/config.ts b/src/tv2_afvd_showstyle/helpers/config.ts index f5e7d4c36..b4a541a73 100644 --- a/src/tv2_afvd_showstyle/helpers/config.ts +++ b/src/tv2_afvd_showstyle/helpers/config.ts @@ -1,43 +1,39 @@ +import { IBlueprintConfig, ICommonContext, IShowStyleContext, TableConfigItemValue } from 'blueprints-integration' import { - IBlueprintConfig, - ICommonContext, - IShowStyleContext, - TableConfigItemValue -} from '@tv2media/blueprints-integration' -import { TableConfigGraphicsSetup, TV2ShowstyleBlueprintConfigBase } from 'tv2-common' + findGraphicsSetup, + TableConfigGraphicsSetup, + TableConfigItemOverlayShowMapping, + TV2ShowstyleBlueprintConfigBase +} from 'tv2-common' import { BlueprintConfig as BlueprintConfigBase } from '../../tv2_afvd_studio/helpers/config' +export interface GalleryTableConfigGraphicsSetup extends TableConfigGraphicsSetup { + VcpConcept: string + FullShowName: string + OvlShowName: string +} + export interface BlueprintConfig extends BlueprintConfigBase { showStyle: ShowStyleConfig - selectedGraphicsSetup: TableConfigGraphicsSetup + selectedGraphicsSetup: GalleryTableConfigGraphicsSetup } export interface ShowStyleConfig extends TV2ShowstyleBlueprintConfigBase { WipesConfig: TableConfigItemValue SelectedGraphicsSetupName: string - GraphicsSetups: TableConfigGraphicsSetup[] -} - -function findGraphicsSetup(context: ICommonContext, config: ShowStyleConfig): TableConfigGraphicsSetup { - const foundTableConfigGraphicsSetup: TableConfigGraphicsSetup | undefined = config.GraphicsSetups.find( - tableConfigGraphicsSetup => tableConfigGraphicsSetup.Name === config.SelectedGraphicsSetupName - ) - if (!foundTableConfigGraphicsSetup) { - context.logWarning(`No graphics setup found for profile: ${config.SelectedGraphicsSetupName}`) - return { - Name: '', - VcpConcept: '', - OvlShowId: '', - FullShowId: '', - DveLayoutFolder: '' - } - } - return foundTableConfigGraphicsSetup + GraphicsSetups: GalleryTableConfigGraphicsSetup[] + OverlayShowMapping: TableConfigItemOverlayShowMapping[] } export function parseConfig(context: ICommonContext, rawConfig: IBlueprintConfig): any { const showstyleConfig = (rawConfig as unknown) as ShowStyleConfig - const selectedGraphicsSetup = findGraphicsSetup(context, showstyleConfig) + const selectedGraphicsSetup = findGraphicsSetup(context, showstyleConfig, { + Name: '', + VcpConcept: '', + OvlShowName: '', + FullShowName: '', + HtmlPackageFolder: '' + }) return { showStyle: showstyleConfig, selectedGraphicsSetup diff --git a/src/tv2_afvd_showstyle/helpers/content/dve.ts b/src/tv2_afvd_showstyle/helpers/content/dve.ts index 8e8cfd6f2..e30d2c168 100644 --- a/src/tv2_afvd_showstyle/helpers/content/dve.ts +++ b/src/tv2_afvd_showstyle/helpers/content/dve.ts @@ -1,4 +1,4 @@ -import { IShowStyleUserContext, SplitsContent, WithTimeline } from '@tv2media/blueprints-integration' +import { IShowStyleUserContext, SplitsContent, WithTimeline } from 'blueprints-integration' import { CueDefinitionDVE, DVEConfigInput, DVEOptions, MakeContentDVEBase, PartDefinition } from 'tv2-common' import { BlueprintConfig } from '../../../tv2_afvd_showstyle/helpers/config' import { AtemLLayer, CasparLLayer, SisyfosLLAyer } from '../../../tv2_afvd_studio/layers' @@ -33,18 +33,7 @@ export function MakeContentDVE( config: BlueprintConfig, partDefinition: PartDefinition, parsedCue: CueDefinitionDVE, - dveConfig: DVEConfigInput | undefined, - addClass?: boolean, - adlib?: boolean + dveConfig: DVEConfigInput | undefined ): { content: WithTimeline; valid: boolean } { - return MakeContentDVEBase( - context, - config, - partDefinition, - parsedCue, - dveConfig, - AFVD_DVE_GENERATOR_OPTIONS, - addClass, - adlib - ) + return MakeContentDVEBase(context, config, partDefinition, parsedCue, dveConfig, AFVD_DVE_GENERATOR_OPTIONS) } 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 81fa9afbd..6a117ed3c 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/__tests__/grafikViz.spec.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/__tests__/grafikViz.spec.ts @@ -6,10 +6,11 @@ import { PieceLifespan, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AtemLLayerDSK, CueDefinitionGraphic, + CueTime, GraphicInternal, GraphicPieceMetaData, GraphicPilot, @@ -21,7 +22,7 @@ import { AdlibTags, CueType, PartType, SharedGraphicLLayer, SharedOutputLayers, import { SegmentUserContext } from '../../../../__mocks__/context' import { parseConfig as parseStudioConfig } from '../../../../tv2_afvd_studio/helpers/config' import mappingsDefaults from '../../../../tv2_afvd_studio/migrations/mappings-defaults' -import { defaultShowStyleConfig, defaultStudioConfig, OVL_SHOW_ID } from '../../../__tests__/configs' +import { defaultShowStyleConfig, defaultStudioConfig, OVL_SHOW_NAME } from '../../../__tests__/configs' import { SourceLayer } from '../../../layers' import { BlueprintConfig, getConfig, parseConfig as parseShowStyleConfig } from '../../config' import { EvaluateCueGraphic } from '../graphic' @@ -49,6 +50,26 @@ const dummyPart = literal({ segmentExternalId: '' }) +function makeTestBundCue(infiniteMode: CueTime['infiniteMode']): CueDefinitionGraphic { + return { + type: CueType.Graphic, + target: 'OVL', + graphic: { + type: 'internal', + template: 'bund', + cue: 'kg', + textFields: ['Odense', 'Copenhagen'] + }, + start: { + seconds: 10 + }, + end: { + infiniteMode + }, + iNewsCommand: 'kg' + } +} + const dskEnableObj = literal({ id: '', enable: { @@ -121,7 +142,8 @@ describe('grafik piece', () => { sisyfosPersistMetaData: { sisyfosLayers: [] }, - belongsToRemotePart: false + partType: PartType.Kam, + pieceExternalId: dummyPart.externalId }, outputLayerId: SharedOutputLayers.OVERLAY, sourceLayerId: SourceLayer.PgmGraphicsLower, @@ -143,7 +165,7 @@ describe('grafik piece', () => { templateName: 'bund', templateData: ['Odense', 'Copenhagen'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), dskEnableObj @@ -216,7 +238,7 @@ describe('grafik piece', () => { templateName: 'bund', templateData: ['Odense', 'Copenhagen'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), dskEnableObj @@ -256,7 +278,7 @@ describe('grafik piece', () => { templateName: 'bund', templateData: ['Odense', 'Copenhagen'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), dskEnableObj @@ -331,7 +353,7 @@ describe('grafik piece', () => { templateName: 'bund', templateData: ['Odense', 'Copenhagen'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), dskEnableObj @@ -371,7 +393,7 @@ describe('grafik piece', () => { templateName: 'bund', templateData: ['Odense', 'Copenhagen'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), dskEnableObj @@ -425,7 +447,8 @@ describe('grafik piece', () => { sisyfosPersistMetaData: { sisyfosLayers: [] }, - belongsToRemotePart: false + partType: PartType.Kam, + pieceExternalId: dummyPart.externalId }, outputLayerId: SharedOutputLayers.OVERLAY, sourceLayerId: SourceLayer.PgmGraphicsLower, @@ -447,7 +470,7 @@ describe('grafik piece', () => { templateName: 'bund', templateData: ['Odense', 'Copenhagen'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), dskEnableObj @@ -457,24 +480,76 @@ describe('grafik piece', () => { ]) }) - test('kg bund infinite', () => { - const cue: CueDefinitionGraphic = { - type: CueType.Graphic, - target: 'OVL', - graphic: { - type: 'internal', - template: 'bund', - cue: 'kg', - textFields: ['Odense', 'Copenhagen'] - }, - start: { - seconds: 10 + test('kg bund infinite (B) has piece and object timing', () => { + const cue = makeTestBundCue('B') + const pieces: IBlueprintPiece[] = [] + const adLibPieces: IBlueprintAdLibPiece[] = [] + const actions: IBlueprintActionManifest[] = [] + const partId = '0000000001' + + EvaluateCueGraphic( + config, + makeMockContext(), + pieces, + adLibPieces, + actions, + partId, + cue, + dummyPart, + cue.adlib ? { rank: 0 } : undefined + ) + expect(pieces.length).toBe(1) + expect(pieces[0]).toMatchObject({ + enable: { + start: 10000 }, - end: { - infiniteMode: 'B' + lifespan: PieceLifespan.WithinPart + }) + expect( + pieces[0].content.timelineObjects.find(tlObject => tlObject.content.deviceType === TSR.DeviceType.VIZMSE) + ).toMatchObject({ + enable: { + while: `!.full` + } + }) + }) + + test('kg bund infinite (S) has piece and object timing', () => { + const cue = makeTestBundCue('S') + const pieces: IBlueprintPiece[] = [] + const adLibPieces: IBlueprintAdLibPiece[] = [] + const actions: IBlueprintActionManifest[] = [] + const partId = '0000000001' + + EvaluateCueGraphic( + config, + makeMockContext(), + pieces, + adLibPieces, + actions, + partId, + cue, + dummyPart, + cue.adlib ? { rank: 0 } : undefined + ) + expect(pieces.length).toBe(1) + expect(pieces[0]).toMatchObject({ + enable: { + start: 10000 }, - iNewsCommand: 'kg' - } + lifespan: PieceLifespan.OutOnSegmentEnd + }) + expect( + pieces[0].content.timelineObjects.find(tlObject => tlObject.content.deviceType === TSR.DeviceType.VIZMSE) + ).toMatchObject({ + enable: { + while: `!.full` + } + }) + }) + + test('kg bund infinite (O)', () => { + const cue = makeTestBundCue('O') const pieces: IBlueprintPiece[] = [] const adLibPieces: IBlueprintAdLibPiece[] = [] const actions: IBlueprintActionManifest[] = [] @@ -491,48 +566,21 @@ describe('grafik piece', () => { dummyPart, cue.adlib ? { rank: 0 } : undefined ) - expect(pieces).toEqual([ - literal>({ - externalId: partId, - name: 'bund - Odense\n - Copenhagen', - enable: { - start: 10000 - }, - lifespan: PieceLifespan.WithinPart, - metaData: { - sisyfosPersistMetaData: { - sisyfosLayers: [] - }, - belongsToRemotePart: false - }, - outputLayerId: SharedOutputLayers.OVERLAY, - sourceLayerId: SourceLayer.PgmGraphicsLower, - content: literal>({ - fileName: 'bund', - path: 'bund', - ignoreMediaObjectStatus: true, - timelineObjects: literal([ - literal({ - id: '', - enable: { - while: `.studio0_parent_camera_1 & !.adlib_deparent & !.full` - }, - priority: 1, - layer: SharedGraphicLLayer.GraphicLLayerOverlayLower, - content: { - deviceType: TSR.DeviceType.VIZMSE, - type: TSR.TimelineContentTypeVizMSE.ELEMENT_INTERNAL, - templateName: 'bund', - templateData: ['Odense', 'Copenhagen'], - channelName: 'OVL1', - showId: OVL_SHOW_ID - } - }), - dskEnableObj - ]) - }) - }) - ]) + + expect(pieces.length).toBe(1) + expect(pieces[0]).toMatchObject({ + enable: { + start: 10000 + }, + lifespan: PieceLifespan.OutOnShowStyleEnd + }) + expect( + pieces[0].content.timelineObjects.find(tlObject => tlObject.content.deviceType === TSR.DeviceType.VIZMSE) + ).toMatchObject({ + enable: { + while: `!.full` + } + }) }) test('kg direkte', () => { @@ -578,7 +626,8 @@ describe('grafik piece', () => { sisyfosPersistMetaData: { sisyfosLayers: [] }, - belongsToRemotePart: false + partType: PartType.Kam, + pieceExternalId: dummyPart.externalId }, outputLayerId: SharedOutputLayers.OVERLAY, sourceLayerId: SourceLayer.PgmGraphicsIdent, @@ -590,7 +639,7 @@ describe('grafik piece', () => { literal({ id: '', enable: { - while: `.studio0_parent_camera_1 & !.adlib_deparent & !.full` + while: `!.full` }, priority: 1, layer: SharedGraphicLLayer.GraphicLLayerOverlayIdent, @@ -600,7 +649,7 @@ describe('grafik piece', () => { templateName: 'direkte', templateData: ['KØBENHAVN'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), dskEnableObj @@ -654,7 +703,8 @@ describe('grafik piece', () => { sisyfosPersistMetaData: { sisyfosLayers: [] }, - belongsToRemotePart: false + partType: PartType.Kam, + pieceExternalId: dummyPart.externalId }, outputLayerId: SharedOutputLayers.OVERLAY, sourceLayerId: SourceLayer.PgmGraphicsIdent, @@ -676,7 +726,7 @@ describe('grafik piece', () => { templateName: 'arkiv', templateData: ['unnamed org'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), dskEnableObj @@ -749,7 +799,7 @@ describe('grafik piece', () => { templateName: 'tlftoptlive', templateData: ['Line 1', 'Line 2'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), dskEnableObj @@ -788,7 +838,7 @@ describe('grafik piece', () => { templateName: 'tlftoptlive', templateData: ['Line 1', 'Line 2'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), dskEnableObj @@ -798,6 +848,92 @@ describe('grafik piece', () => { ]) }) + test('kg tlftoptlive: timecode has priority over OutType column', () => { + const cue = literal>({ + type: CueType.Graphic, + target: 'OVL', + graphic: { + type: 'internal', + template: 'tlftoptlive', + cue: 'kg', + textFields: ['Line 1', 'Line 2'] + }, + start: { + seconds: 5 + }, + end: { + seconds: 10 + }, + iNewsCommand: 'kg' + }) + const pieces: IBlueprintPiece[] = [] + const adLibPieces: IBlueprintAdLibPiece[] = [] + const actions: IBlueprintActionManifest[] = [] + const partId = '0000000001' + + EvaluateCueGraphic( + config, + makeMockContext(), + pieces, + adLibPieces, + actions, + partId, + cue, + dummyPart, + cue.adlib ? { rank: 0 } : undefined + ) + + expect(pieces.length).toBe(1) + expect(pieces[0]).toMatchObject({ + enable: { + start: 5000, + duration: 5000 + }, + lifespan: PieceLifespan.WithinPart + }) + }) + + test('kg tlftoptlive adilb: timecode has priority over OutType column', () => { + const cue = literal>({ + type: CueType.Graphic, + target: 'OVL', + graphic: { + type: 'internal', + template: 'tlftoptlive', + cue: 'kg', + textFields: ['Line 1', 'Line 2'] + }, + end: { + seconds: 10 + }, + adlib: true, + iNewsCommand: 'kg' + }) + const pieces: IBlueprintPiece[] = [] + const adLibPieces: IBlueprintAdLibPiece[] = [] + const actions: IBlueprintActionManifest[] = [] + const partId = '0000000001' + + EvaluateCueGraphic( + config, + makeMockContext(), + pieces, + adLibPieces, + actions, + partId, + cue, + dummyPart, + cue.adlib ? { rank: 0 } : undefined + ) + + const adlibPiece = adLibPieces.find(piece => piece.tags?.includes('flow_producer')) + expect(adlibPiece).toBeDefined() + expect(adlibPiece).toMatchObject({ + expectedDuration: 10000, + lifespan: PieceLifespan.WithinPart + }) + }) + it('WALL graphics have enable equal while 1', () => { const cue: CueDefinitionGraphic = { type: CueType.Graphic, 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 53fdaea3a..5ed3827fe 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/__tests__/lyd.spec.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/__tests__/lyd.spec.ts @@ -4,7 +4,7 @@ import { IBlueprintPiece, PieceLifespan, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CueDefinitionLYD, EvaluateLYD, literal, ParseCue, PartDefinitionKam } from 'tv2-common' import { AdlibTags, NoteType, PartType, SharedOutputLayers, SharedSourceLayers, SourceType } from 'tv2-constants' import { SegmentUserContext } from '../../../../__mocks__/context' 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 fb075a18d..61c358f6b 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/__tests__/telefon.spec.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/__tests__/telefon.spec.ts @@ -6,7 +6,7 @@ import { PieceLifespan, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AtemLLayerDSK, CueDefinitionGraphic, @@ -22,7 +22,7 @@ import { DEFAULT_GRAPHICS_SETUP, defaultShowStyleConfig, defaultStudioConfig, - OVL_SHOW_ID + OVL_SHOW_NAME } from '../../../../tv2_afvd_showstyle/__tests__/configs' import { SourceLayer } from '../../../../tv2_afvd_showstyle/layers' import { @@ -116,10 +116,11 @@ describe('telefon', () => { sourceLayerId: SourceLayer.PgmGraphicsLower, lifespan: PieceLifespan.WithinPart, metaData: { - belongsToRemotePart: false, sisyfosPersistMetaData: { sisyfosLayers: [] - } + }, + partType: PartType.Kam, + pieceExternalId: dummyPart.externalId }, content: literal>({ fileName: 'bund', @@ -139,7 +140,7 @@ describe('telefon', () => { templateName: 'bund', templateData: ['Odense', 'Copenhagen'], channelName: 'OVL1', - showId: OVL_SHOW_ID + showId: OVL_SHOW_NAME } }), literal({ diff --git a/src/tv2_afvd_showstyle/helpers/pieces/adlib.ts b/src/tv2_afvd_showstyle/helpers/pieces/adlib.ts index 3c2864882..82cbea1bb 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/adlib.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/adlib.ts @@ -1,21 +1,18 @@ import { HackPartMediaObjectSubscription, IBlueprintActionManifest, - IBlueprintAdLibPiece, - IShowStyleUserContext, - PieceLifespan -} from '@tv2media/blueprints-integration' + IShowStyleUserContext +} from 'blueprints-integration' import { ActionSelectDVE, CreateAdlibServer, CueDefinitionAdLib, CueDefinitionDVE, - DVEPieceMetaData, + generateExternalId, GetDVETemplate, getUniquenessIdDVE, - literal, PartDefinition, - PieceMetaData, + t, TemplateIsValid } from 'tv2-common' import { AdlibActionType, AdlibTags, CueType, SharedOutputLayers } from 'tv2-constants' @@ -27,10 +24,8 @@ import { MakeContentDVE } from '../content/dve' export async function EvaluateAdLib( context: IShowStyleUserContext, config: BlueprintConfig, - adLibPieces: Array>, actions: IBlueprintActionManifest[], mediaSubscriptions: HackPartMediaObjectSubscription[], - partId: string, parsedCue: CueDefinitionAdLib, partDefinition: PartDefinition, rank: number @@ -98,33 +93,28 @@ export async function EvaluateAdLib( iNewsCommand: 'DVE' } - const content = MakeContentDVE(context, config, partDefinition, cueDVE, rawTemplate, false, true) + const content = MakeContentDVE(context, config, partDefinition, cueDVE, rawTemplate) - 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 - }), - sisyfosPersistMetaData: { - sisyfosLayers: [] - } - }), - tags: [AdlibTags.ADLIB_FLOW_PRODUCER] + const userData: ActionSelectDVE = { + type: AdlibActionType.SELECT_DVE, + config: cueDVE, + name: `DVE: ${cueDVE.template}`, + videoId: partDefinition.fields.videoId, + segmentExternalId: partDefinition.segmentExternalId + } + actions.push({ + externalId: generateExternalId(context, userData), + actionId: AdlibActionType.SELECT_DVE, + userData, + userDataManifest: {}, + display: { + sourceLayerId: SourceLayer.PgmDVE, + outputLayerId: SharedOutputLayers.PGM, + uniquenessId: getUniquenessIdDVE(cueDVE), + label: t(`${partDefinition.storyName}`), + tags: [AdlibTags.ADLIB_FLOW_PRODUCER], + content: content.content + } }) } } diff --git a/src/tv2_afvd_showstyle/helpers/pieces/clearGrafiks.ts b/src/tv2_afvd_showstyle/helpers/pieces/clearGrafiks.ts index 202258d60..55b7cc954 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/clearGrafiks.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/clearGrafiks.ts @@ -4,7 +4,7 @@ import { IBlueprintPiece, PieceLifespan, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CreateTimingEnable, CueDefinitionClearGrafiks, GetDefaultOut, literal } from 'tv2-common' import { SharedGraphicLLayer, SharedOutputLayers } from 'tv2-constants' import { BlueprintConfig } from '../../../tv2_afvd_showstyle/helpers/config' @@ -69,7 +69,7 @@ export function EvaluateClearGrafiks( content: { deviceType: TSR.DeviceType.VIZMSE, type: TSR.TimelineContentTypeVizMSE.CLEAR_ALL_ELEMENTS, - showId: config.selectedGraphicsSetup.OvlShowId + showId: config.selectedGraphicsSetup.OvlShowName } }) ] diff --git a/src/tv2_afvd_showstyle/helpers/pieces/design.ts b/src/tv2_afvd_showstyle/helpers/pieces/design.ts index 09d8c7764..af0d22e13 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/design.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/design.ts @@ -3,7 +3,7 @@ import { IBlueprintAdLibPiece, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CueDefinitionGraphicDesign, EvaluateDesignBase, TV2BlueprintConfig } from 'tv2-common' import * as _ from 'underscore' diff --git a/src/tv2_afvd_showstyle/helpers/pieces/dve.ts b/src/tv2_afvd_showstyle/helpers/pieces/dve.ts index 0a5e4ee7b..e4db171f8 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/dve.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/dve.ts @@ -1,23 +1,18 @@ -import { - IBlueprintActionManifest, - IBlueprintAdLibPiece, - IBlueprintPiece, - ISegmentUserContext, - PieceLifespan -} from '@tv2media/blueprints-integration' +import { IBlueprintActionManifest, IBlueprintPiece, ISegmentUserContext, PieceLifespan } from 'blueprints-integration' import { ActionSelectDVE, - AddParentClass, CalculateTime, CueDefinitionDVE, DVEPieceMetaData, + generateExternalId, GetDVETemplate, getUniquenessIdDVE, literal, PartDefinition, + t, TemplateIsValid } from 'tv2-common' -import { AdlibActionType, SharedOutputLayers } from 'tv2-constants' +import { AdlibActionType, AdlibTags, SharedOutputLayers } from 'tv2-constants' import { BlueprintConfig } from '../../../tv2_afvd_showstyle/helpers/config' import { SourceLayer } from '../../../tv2_afvd_showstyle/layers' import { MakeContentDVE } from '../content/dve' @@ -26,8 +21,7 @@ export function EvaluateDVE( context: ISegmentUserContext, config: BlueprintConfig, pieces: IBlueprintPiece[], - adlibPieces: IBlueprintAdLibPiece[], - _actions: IBlueprintActionManifest[], + actions: IBlueprintActionManifest[], partDefinition: PartDefinition, parsedCue: CueDefinitionDVE, adlib?: boolean, @@ -48,53 +42,41 @@ export function EvaluateDVE( return } - const content = MakeContentDVE( - context, - config, - partDefinition, - parsedCue, - rawTemplate, - AddParentClass(config, partDefinition), - adlib - ) + const content = MakeContentDVE(context, config, partDefinition, parsedCue, rawTemplate) if (content.valid) { if (adlib) { - adlibPieces.push( - literal>({ - _rank: rank || 0, - externalId: partDefinition.externalId, - name: `${partDefinition.storyName} DVE: ${parsedCue.template}`, + const userData: ActionSelectDVE = { + type: AdlibActionType.SELECT_DVE, + config: parsedCue, + name: `${partDefinition.storyName} DVE: ${parsedCue.template}`, + videoId: partDefinition.fields.videoId, + segmentExternalId: partDefinition.segmentExternalId + } + actions.push({ + externalId: generateExternalId(context, userData), + actionId: AdlibActionType.SELECT_DVE, + userData, + userDataManifest: {}, + display: { + _rank: rank, outputLayerId: SharedOutputLayers.PGM, sourceLayerId: SourceLayer.PgmDVE, - uniquenessId: getUniquenessIdDVE(parsedCue), - lifespan: PieceLifespan.WithinPart, - toBeQueued: true, + label: t(`${partDefinition.storyName} DVE: ${parsedCue.template}`), + tags: [AdlibTags.ADLIB_FLOW_PRODUCER], content: content.content, - prerollDuration: Number(config.studio.CasparPrerollDuration) || 0, - metaData: { - sources: parsedCue.sources, - config: rawTemplate, - userData: literal({ - type: AdlibActionType.SELECT_DVE, - config: parsedCue, - videoId: partDefinition.fields.videoId, - segmentExternalId: partDefinition.segmentExternalId - }), - sisyfosPersistMetaData: { - sisyfosLayers: [] - } - } - }) - ) + uniquenessId: getUniquenessIdDVE(parsedCue) + } + }) } else { let start = parsedCue.start ? CalculateTime(parsedCue.start) : 0 start = start ? start : 0 const end = parsedCue.end ? CalculateTime(parsedCue.end) : undefined + const pieceName = `DVE: ${parsedCue.template}` pieces.push( literal>({ externalId: partDefinition.externalId, - name: `DVE: ${parsedCue.template}`, + name: pieceName, enable: { start, ...(end ? { duration: end - start } : {}) @@ -112,6 +94,7 @@ export function EvaluateDVE( userData: { type: AdlibActionType.SELECT_DVE, config: parsedCue, + name: pieceName, videoId: partDefinition.fields.videoId, segmentExternalId: partDefinition.segmentExternalId }, diff --git a/src/tv2_afvd_showstyle/helpers/pieces/ekstern.ts b/src/tv2_afvd_showstyle/helpers/pieces/ekstern.ts index ac382dc39..1426431e1 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/ekstern.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/ekstern.ts @@ -4,7 +4,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CueDefinitionEkstern, EvaluateEksternBase, diff --git a/src/tv2_afvd_showstyle/helpers/pieces/evaluateCues.ts b/src/tv2_afvd_showstyle/helpers/pieces/evaluateCues.ts index 46dc27b6f..9ae85a174 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/evaluateCues.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/evaluateCues.ts @@ -5,10 +5,11 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CueDefinition, EvaluateCueMixMinus, + EvaluateCueRobotCamera, EvaluateCuesBase, EvaluateCuesOptions, EvaluateLYD, @@ -51,7 +52,8 @@ export async function EvaluateCues( EvaluateCueBackgroundLoop, EvaluateCueGraphicDesign: EvaluateCueDesign, EvaluateCueRouting, - EvaluateCueMixMinus + EvaluateCueMixMinus, + EvaluateCueRobotCamera }, context, config, diff --git a/src/tv2_afvd_showstyle/helpers/pieces/graphic.ts b/src/tv2_afvd_showstyle/helpers/pieces/graphic.ts index dbd656b19..6f679233e 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/graphic.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/graphic.ts @@ -3,7 +3,7 @@ import { IBlueprintAdLibPiece, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { Adlib, CreateInternalGraphic, diff --git a/src/tv2_afvd_showstyle/helpers/pieces/graphicBackgroundLoop.ts b/src/tv2_afvd_showstyle/helpers/pieces/graphicBackgroundLoop.ts index 3e39ff3de..f699720a7 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/graphicBackgroundLoop.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/graphicBackgroundLoop.ts @@ -6,7 +6,7 @@ import { PieceLifespan, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CalculateTime, CueDefinitionBackgroundLoop, literal, TV2BlueprintConfig } from 'tv2-common' import { SharedGraphicLLayer, SharedOutputLayers } from 'tv2-constants' import { CasparLLayer } from '../../../tv2_afvd_studio/layers' @@ -116,6 +116,9 @@ function dveLoopTimeline(path: string): TSR.TSRTimelineObj[] { } function fullLoopTimeline(config: TV2BlueprintConfig, parsedCue: CueDefinitionBackgroundLoop): TSR.TSRTimelineObj[] { + if (!config.selectedGraphicsSetup.FullShowName) { + return [] + } return [ literal({ id: '', @@ -127,7 +130,7 @@ function fullLoopTimeline(config: TV2BlueprintConfig, parsedCue: CueDefinitionBa type: TSR.TimelineContentTypeVizMSE.ELEMENT_INTERNAL, templateName: parsedCue.backgroundLoop, templateData: [], - showId: config.selectedGraphicsSetup.FullShowId + showId: config.selectedGraphicsSetup.FullShowName } }) ] diff --git a/src/tv2_afvd_showstyle/helpers/pieces/graphicPilot.ts b/src/tv2_afvd_showstyle/helpers/pieces/graphicPilot.ts index d0a68e0da..d4ec238f9 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/graphicPilot.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/graphicPilot.ts @@ -3,9 +3,8 @@ import { IBlueprintAdLibPiece, IBlueprintPiece, IShowStyleUserContext, - IStudioUserContext, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { Adlib, CreatePilotGraphic, @@ -22,8 +21,8 @@ import { AtemLLayer } from '../../../tv2_afvd_studio/layers' import { BlueprintConfig } from '../config' export const pilotGeneratorSettingsAFVD: PilotGeneratorSettings = { - caspar: { createPilotTimelineForStudio: makeStudioTimelineCaspar }, - viz: { createPilotTimelineForStudio: makeStudioTimelineViz } + caspar: { createFullPilotTimelineForStudio: makeStudioTimelineCaspar }, + viz: { createFullPilotTimelineForStudio: makeStudioTimelineViz } } export function EvaluateCueGraphicPilot( @@ -40,7 +39,6 @@ export function EvaluateCueGraphicPilot( CreatePilotGraphic(pieces, adlibPieces, actions, { config, context, - engine: parsedCue.target, partId, parsedCue, settings: pilotGeneratorSettingsAFVD, @@ -49,11 +47,7 @@ export function EvaluateCueGraphicPilot( }) } -function makeStudioTimelineViz( - config: BlueprintConfig, - _context: IStudioUserContext, - adlib: boolean -): TSR.TSRTimelineObj[] { +function makeStudioTimelineViz(config: BlueprintConfig): TSR.TSRTimelineObj[] { const fullDSK = FindDSKFullGFX(config) return [ @@ -71,8 +65,7 @@ function makeStudioTimelineViz( input: config.studio.VizPilotGraphics.FullGraphicBackground, transition: TSR.AtemTransitionStyle.CUT } - }, - ...(adlib ? { classes: ['adlib_deparent'] } : {}) + } }), literal({ id: '', @@ -96,7 +89,7 @@ function makeStudioTimelineViz( ] } -function makeStudioTimelineCaspar(config: BlueprintConfig, _context: IStudioUserContext) { +function makeStudioTimelineCaspar(config: BlueprintConfig) { const fullDSK = FindDSKFullGFX(config) return [ literal({ diff --git a/src/tv2_afvd_showstyle/helpers/pieces/jingle.ts b/src/tv2_afvd_showstyle/helpers/pieces/jingle.ts index 706c6b3f9..465560a8b 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/jingle.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/jingle.ts @@ -4,7 +4,7 @@ import { IBlueprintPiece, ISegmentUserContext, PieceLifespan -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionSelectJingle, CreateJingleContentBase, diff --git a/src/tv2_afvd_showstyle/helpers/pieces/routing.ts b/src/tv2_afvd_showstyle/helpers/pieces/routing.ts index cf116a812..bf080c2b1 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/routing.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/routing.ts @@ -7,7 +7,7 @@ import { PieceLifespan, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CalculateTime, CueDefinitionRouting, findSourceInfo, literal, TV2BlueprintConfig } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' import _ = require('underscore') diff --git a/src/tv2_afvd_showstyle/helpers/pieces/showLifecycle.ts b/src/tv2_afvd_showstyle/helpers/pieces/showLifecycle.ts index 691b2c59b..e9613f93d 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, PieceLifespan, TSR } from '@tv2media/blueprints-integration' +import { BlueprintResultPart, PieceLifespan, TSR } from 'blueprints-integration' import { literal, TV2BlueprintConfig } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' import { GraphicLLayer } from '../../../tv2_afvd_studio/layers' diff --git a/src/tv2_afvd_showstyle/helpers/pieces/telefon.ts b/src/tv2_afvd_showstyle/helpers/pieces/telefon.ts index f6e156909..5ff91195b 100644 --- a/src/tv2_afvd_showstyle/helpers/pieces/telefon.ts +++ b/src/tv2_afvd_showstyle/helpers/pieces/telefon.ts @@ -3,7 +3,7 @@ import { IBlueprintAdLibPiece, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { Adlib, CueDefinitionTelefon, diff --git a/src/tv2_afvd_showstyle/helpers/studio.ts b/src/tv2_afvd_showstyle/helpers/studio.ts index 3113df726..23597efa1 100644 --- a/src/tv2_afvd_showstyle/helpers/studio.ts +++ b/src/tv2_afvd_showstyle/helpers/studio.ts @@ -1,4 +1,4 @@ -import { IStudioContext } from '@tv2media/blueprints-integration' +import { IStudioContext } from 'blueprints-integration' /** * Gets the name of the studio this context belongs to. diff --git a/src/tv2_afvd_showstyle/index.ts b/src/tv2_afvd_showstyle/index.ts index e39af102f..5b9d8b01d 100644 --- a/src/tv2_afvd_showstyle/index.ts +++ b/src/tv2_afvd_showstyle/index.ts @@ -1,10 +1,9 @@ -import { BlueprintManifestType, ShowStyleBlueprintManifest } from '@tv2media/blueprints-integration' -import { getShowStyleVariantId } from '../tv2-common/getShowStyleVariantId' +import { BlueprintManifestType, ShowStyleBlueprintManifest } from 'blueprints-integration' +import { getEndStateForPart, getShowStyleVariantId } from 'tv2-common' import { showStyleConfigManifest } from './config-manifests' import { showStyleMigrations } from './migrations' import { GetShowStyleManifestWithMixins, ShowStyleManifestMixinINews } from 'inews-mixins' -import { getEndStateForPart, shouldRemoveOrphanedPartInstance } from 'tv2-common' import { onTimelineGenerateAFVD } from '../tv2_afvd_studio/onTimelineGenerate' import { executeActionAFVD } from './actions' import { getRundown } from './getRundown' @@ -23,7 +22,6 @@ const manifest: ShowStyleBlueprintManifest = GetShowStyleManifestWithMixins( blueprintVersion: VERSION, integrationVersion: VERSION_INTEGRATION, TSRVersion: VERSION_TSR, - preprocessConfig: parseConfig, getShowStyleVariantId, @@ -34,7 +32,6 @@ const manifest: ShowStyleBlueprintManifest = GetShowStyleManifestWithMixins( getEndStateForPart, executeAction: executeActionAFVD, syncIngestUpdateToPartInstance, - shouldRemoveOrphanedPartInstance, showStyleConfigManifest, showStyleMigrations diff --git a/src/tv2_afvd_showstyle/migrations/hotkeys.ts b/src/tv2_afvd_showstyle/migrations/hotkeys.ts index 979843c4b..5c428b3f3 100644 --- a/src/tv2_afvd_showstyle/migrations/hotkeys.ts +++ b/src/tv2_afvd_showstyle/migrations/hotkeys.ts @@ -1,8 +1,4 @@ -import { - ConfigManifestEntryTable, - MigrationContextShowStyle, - TableConfigItemValue -} from '@tv2media/blueprints-integration' +import { ConfigManifestEntryTable, MigrationContextShowStyle, TableConfigItemValue } from 'blueprints-integration' import { GlobalHotkeySources } from 'tv2-common' import { manifestAFVDSourcesCam, diff --git a/src/tv2_afvd_showstyle/migrations/index.ts b/src/tv2_afvd_showstyle/migrations/index.ts index 302146dc7..562deedf7 100644 --- a/src/tv2_afvd_showstyle/migrations/index.ts +++ b/src/tv2_afvd_showstyle/migrations/index.ts @@ -1,11 +1,13 @@ -import { MigrationStepShowStyle, SourceLayerType } from '@tv2media/blueprints-integration' +import { MigrationStepShowStyle, SourceLayerType } from 'blueprints-integration' import { - AddGraphicToGFXTable, - changeGFXTemplate, + AddGraphicToGfxTable, + changeGfxTemplate, GetDefaultAdLibTriggers, GetDSKSourceLayerNames, + mapGfxTemplateToDesignTemplateAndDeleteOriginals, RemoveOldShortcuts, removeSourceLayer, + renameTableColumn, SetShowstyleTransitionMigrationStep, SetSourceLayerName, SetSourceLayerProperties, @@ -38,9 +40,9 @@ const SHOW_STYLE_ID = 'tv2_afvd_showstyle' export const showStyleMigrations: MigrationStepShowStyle[] = [ ...getCreateVariantMigrationSteps(), - ...remapTableColumnValues('0.1.0', 'GFXTemplates', 'LayerMapping', remapVizLLayer), + remapTableColumnValues('0.1.0', 'GFXTemplates', 'LayerMapping', remapVizLLayer), // Rename "viz-d-ovl" to "OVL1" - ...remapTableColumnValues('0.1.0', 'GFXTemplates', 'VizDestination', remapVizDOvl), + remapTableColumnValues('0.1.0', 'GFXTemplates', 'VizDestination', remapVizDOvl), // Update all defaults for 1.3.0 ...getSourceLayerDefaultsMigrationSteps('1.3.0', true), @@ -79,7 +81,7 @@ export const showStyleMigrations: MigrationStepShowStyle[] = [ */ forceSourceLayerToDefaults('1.5.2', SourceLayer.PgmJingle), - AddGraphicToGFXTable('1.5.4', 'AFVD', { + AddGraphicToGfxTable('1.5.4', 'AFVD', { VizTemplate: 'locators', SourceLayer: '', LayerMapping: SharedGraphicLLayer.GraphicLLayerLocators, @@ -190,7 +192,7 @@ export const showStyleMigrations: MigrationStepShowStyle[] = [ * 1.7.2 * - Fix bundright configuration */ - changeGFXTemplate( + changeGfxTemplate( '1.7.2', 'AFVD', { @@ -202,7 +204,7 @@ export const showStyleMigrations: MigrationStepShowStyle[] = [ }, { OutType: '' } ), - changeGFXTemplate( + changeGfxTemplate( '1.7.2', 'AFVD', { @@ -214,7 +216,7 @@ export const showStyleMigrations: MigrationStepShowStyle[] = [ }, { SourceLayer: 'studio0_graphicsLower' } ), - changeGFXTemplate( + changeGfxTemplate( '1.7.2', 'AFVD', { @@ -233,6 +235,21 @@ export const showStyleMigrations: MigrationStepShowStyle[] = [ */ removeSourceLayer('1.7.5', 'AFVD', 'studio0_graphicsIdent_persistent'), + /** + * 1.7.6 + * - Rename columns in Graphics Setups table + * - Map designs from GFXTemplates to GfxDesignTemplates and delete them from GFXTemplates + */ + renameTableColumn('1.7.6', 'GraphicsSetups', 'OvlShowId', 'OvlShowName'), + renameTableColumn('1.7.6', 'GraphicsSetups', 'FullShowId', 'FullShowName'), + mapGfxTemplateToDesignTemplateAndDeleteOriginals('1.7.6', 'AFVD', 'GFXTemplates', 'GfxDesignTemplates'), + + /** + * 1.7.7 + * - Update SourceLayerType for Continuity + */ + forceSourceLayerToDefaults('1.7.7', SourceLayer.PgmContinuity), + // 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 ...getSourceLayerDefaultsMigrationSteps(VERSION), diff --git a/src/tv2_afvd_showstyle/migrations/outputlayer-defaults.ts b/src/tv2_afvd_showstyle/migrations/outputlayer-defaults.ts index bc6709923..1c01fad86 100644 --- a/src/tv2_afvd_showstyle/migrations/outputlayer-defaults.ts +++ b/src/tv2_afvd_showstyle/migrations/outputlayer-defaults.ts @@ -1,4 +1,4 @@ -import { IOutputLayer } from '@tv2media/blueprints-integration' +import { IOutputLayer } from 'blueprints-integration' import { literal } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' diff --git a/src/tv2_afvd_showstyle/migrations/sourcelayer-defaults.ts b/src/tv2_afvd_showstyle/migrations/sourcelayer-defaults.ts index 1571e6a5a..d87056982 100644 --- a/src/tv2_afvd_showstyle/migrations/sourcelayer-defaults.ts +++ b/src/tv2_afvd_showstyle/migrations/sourcelayer-defaults.ts @@ -1,4 +1,4 @@ -import { ISourceLayer, SourceLayerType } from '@tv2media/blueprints-integration' +import { ISourceLayer, SourceLayerType } from 'blueprints-integration' import { GetDSKSourceLayerDefaults, literal } from 'tv2-common' import { SharedSourceLayers } from 'tv2-constants' import { ATEMModel } from '../../types/atem' @@ -337,7 +337,7 @@ const PGM: ISourceLayer[] = [ _rank: 0, name: 'Continuity', abbreviation: 'CONTINUITY', - type: SourceLayerType.METADATA, + type: SourceLayerType.UNKNOWN, exclusiveGroup: 'me1', isRemoteInput: false, isGuestInput: false, @@ -513,6 +513,23 @@ const SEC: ISourceLayer[] = [ isSticky: false, + isQueueable: false, + isHidden: false, + allowDisable: false, + onPresenterScreen: false + }, + { + _id: SharedSourceLayers.RobotCamera, + _rank: 70, + name: 'Robot Camera', + abbreviation: '', + type: SourceLayerType.UNKNOWN, + exclusiveGroup: '', + isRemoteInput: false, + isGuestInput: false, + + isSticky: false, + isQueueable: false, isHidden: false, allowDisable: false, diff --git a/src/tv2_afvd_showstyle/migrations/util.ts b/src/tv2_afvd_showstyle/migrations/util.ts index a49f04d82..0c0f93b18 100644 --- a/src/tv2_afvd_showstyle/migrations/util.ts +++ b/src/tv2_afvd_showstyle/migrations/util.ts @@ -1,9 +1,4 @@ -import { - IOutputLayer, - ISourceLayer, - MigrationContextShowStyle, - MigrationStepShowStyle -} from '@tv2media/blueprints-integration' +import { IOutputLayer, ISourceLayer, MigrationContextShowStyle, MigrationStepShowStyle } from 'blueprints-integration' import { forceSourceLayerToDefaultsBase, literal } from 'tv2-common' import * as _ from 'underscore' import { showStyleConfigManifest } from '../config-manifests' diff --git a/src/tv2_afvd_showstyle/migrations/variants-defaults.ts b/src/tv2_afvd_showstyle/migrations/variants-defaults.ts index 2767d6458..90827f882 100644 --- a/src/tv2_afvd_showstyle/migrations/variants-defaults.ts +++ b/src/tv2_afvd_showstyle/migrations/variants-defaults.ts @@ -1,4 +1,4 @@ -import { MigrationContextShowStyle, MigrationStepShowStyle } from '@tv2media/blueprints-integration' +import { MigrationContextShowStyle, MigrationStepShowStyle } from 'blueprints-integration' import { literal } from 'tv2-common' import * as _ from 'underscore' diff --git a/src/tv2_afvd_showstyle/parts/cueonly.ts b/src/tv2_afvd_showstyle/parts/cueonly.ts index c378d7fb9..19f2b0e70 100644 --- a/src/tv2_afvd_showstyle/parts/cueonly.ts +++ b/src/tv2_afvd_showstyle/parts/cueonly.ts @@ -5,7 +5,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, ApplyFullGraphicPropertiesToPart, diff --git a/src/tv2_afvd_showstyle/parts/effekt.ts b/src/tv2_afvd_showstyle/parts/effekt.ts index 8cd6b8be9..8dd53bbb8 100644 --- a/src/tv2_afvd_showstyle/parts/effekt.ts +++ b/src/tv2_afvd_showstyle/parts/effekt.ts @@ -1,4 +1,4 @@ -import { IBlueprintPiece, ISegmentUserContext } from '@tv2media/blueprints-integration' +import { IBlueprintPiece, ISegmentUserContext } from 'blueprints-integration' import { CreateEffektForPartBase, PartDefinition } from 'tv2-common' import { CasparLLayer, SisyfosLLAyer } from '../../tv2_afvd_studio/layers' import { BlueprintConfig } from '../helpers/config' diff --git a/src/tv2_afvd_showstyle/parts/evs.ts b/src/tv2_afvd_showstyle/parts/evs.ts index b2ab05004..0fb00e95f 100644 --- a/src/tv2_afvd_showstyle/parts/evs.ts +++ b/src/tv2_afvd_showstyle/parts/evs.ts @@ -9,11 +9,10 @@ import { PieceLifespan, TimelineObjectCoreExt, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, CreatePartInvalid, - EVSParentClass, findSourceInfo, GetSisyfosTimelineObjForReplay, literal, @@ -128,8 +127,7 @@ function makeContentEVS( transition: partDefinition.transition ? partDefinition.transition.style : TSR.AtemTransitionStyle.CUT, transitionSettings: TransitionSettings(config, partDefinition) } - }, - classes: [EVSParentClass('studio0', partDefinition.sourceDefinition.id)] + } }), ...GetSisyfosTimelineObjForReplay(config, sourceInfoReplay, partDefinition.sourceDefinition.vo) ]) diff --git a/src/tv2_afvd_showstyle/parts/grafik.ts b/src/tv2_afvd_showstyle/parts/grafik.ts index 23b2121d1..fa869c018 100644 --- a/src/tv2_afvd_showstyle/parts/grafik.ts +++ b/src/tv2_afvd_showstyle/parts/grafik.ts @@ -6,7 +6,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, ApplyFullGraphicPropertiesToPart, GraphicIsPilot, PartDefinition, PartTime } from 'tv2-common' import { CueType } from 'tv2-constants' import { BlueprintConfig } from '../helpers/config' diff --git a/src/tv2_afvd_showstyle/parts/intro.ts b/src/tv2_afvd_showstyle/parts/intro.ts index d62a2c4a6..55d7b86d4 100644 --- a/src/tv2_afvd_showstyle/parts/intro.ts +++ b/src/tv2_afvd_showstyle/parts/intro.ts @@ -6,7 +6,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, CreatePartInvalid, diff --git a/src/tv2_afvd_showstyle/parts/kam.ts b/src/tv2_afvd_showstyle/parts/kam.ts index c280c73bf..c1a570de1 100644 --- a/src/tv2_afvd_showstyle/parts/kam.ts +++ b/src/tv2_afvd_showstyle/parts/kam.ts @@ -10,11 +10,9 @@ import { TSR, VTContent, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { - AddParentClass, AddScript, - CameraParentClass, CreatePartInvalid, CreatePartKamBase, FindDSKJingle, @@ -51,7 +49,7 @@ export async function CreatePartKam( const jingleDSK = FindDSKJingle(config) - if (partDefinition.rawType.match(/kam cs ?3/i)) { + if (/\bcs *\d*/i.test(partDefinition.sourceDefinition.id)) { pieces.push({ externalId: partDefinition.externalId, name: 'CS 3 (JINGLE)', @@ -132,10 +130,7 @@ export async function CreatePartKam( 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) ]) diff --git a/src/tv2_afvd_showstyle/parts/live.ts b/src/tv2_afvd_showstyle/parts/live.ts index 6da5eb433..5331e293b 100644 --- a/src/tv2_afvd_showstyle/parts/live.ts +++ b/src/tv2_afvd_showstyle/parts/live.ts @@ -6,7 +6,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, CueDefinitionEkstern, PartDefinition, PartTime } from 'tv2-common' import { CueType } from 'tv2-constants' import { BlueprintConfig } from '../../tv2_afvd_showstyle/helpers/config' diff --git a/src/tv2_afvd_showstyle/parts/server.ts b/src/tv2_afvd_showstyle/parts/server.ts index d0890b734..b7ffb80a3 100644 --- a/src/tv2_afvd_showstyle/parts/server.ts +++ b/src/tv2_afvd_showstyle/parts/server.ts @@ -3,7 +3,7 @@ import { HackPartMediaObjectSubscription, IBlueprintActionManifest, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, CreatePartServerBase, PartDefinition, ServerPartProps } from 'tv2-common' import { AtemLLayer, CasparLLayer, SisyfosLLAyer } from '../../tv2_afvd_studio/layers' import { BlueprintConfig } from '../helpers/config' diff --git a/src/tv2_afvd_showstyle/parts/teknik.ts b/src/tv2_afvd_showstyle/parts/teknik.ts index f93bd2386..0eedccef5 100644 --- a/src/tv2_afvd_showstyle/parts/teknik.ts +++ b/src/tv2_afvd_showstyle/parts/teknik.ts @@ -6,7 +6,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, PartDefinition, PartTime } from 'tv2-common' import { BlueprintConfig } from '../helpers/config' import { EvaluateCues } from '../helpers/pieces/evaluateCues' diff --git a/src/tv2_afvd_showstyle/parts/unknown.ts b/src/tv2_afvd_showstyle/parts/unknown.ts index 6f991fbe2..802864629 100644 --- a/src/tv2_afvd_showstyle/parts/unknown.ts +++ b/src/tv2_afvd_showstyle/parts/unknown.ts @@ -5,7 +5,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, ApplyFullGraphicPropertiesToPart, diff --git a/src/tv2_afvd_showstyle/postProcessTimelineObjects.ts b/src/tv2_afvd_showstyle/postProcessTimelineObjects.ts index 14ace1ff0..152bc5829 100644 --- a/src/tv2_afvd_showstyle/postProcessTimelineObjects.ts +++ b/src/tv2_afvd_showstyle/postProcessTimelineObjects.ts @@ -8,7 +8,7 @@ import { TimelineObjectCoreExt, TimelineObjHoldMode, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AtemLLayerDSK, FindDSKJingle, TimelineBlueprintExt } from 'tv2-common' import * as _ from 'underscore' import { AtemLLayer } from '../tv2_afvd_studio/layers' diff --git a/src/tv2_afvd_showstyle/syncIngestUpdateToPartInstance.ts b/src/tv2_afvd_showstyle/syncIngestUpdateToPartInstance.ts index 2aa947b25..630090cf2 100644 --- a/src/tv2_afvd_showstyle/syncIngestUpdateToPartInstance.ts +++ b/src/tv2_afvd_showstyle/syncIngestUpdateToPartInstance.ts @@ -2,7 +2,7 @@ import { BlueprintSyncIngestNewData, BlueprintSyncIngestPartInstance, ISyncIngestUpdateToPartInstanceContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { syncIngestUpdateToPartInstanceBase } from 'tv2-common' import * as _ from 'underscore' import { SourceLayer } from './layers' diff --git a/src/tv2_afvd_studio/__tests__/graphics.spec.ts b/src/tv2_afvd_studio/__tests__/graphics.spec.ts index fab91a42a..939664279 100644 --- a/src/tv2_afvd_studio/__tests__/graphics.spec.ts +++ b/src/tv2_afvd_studio/__tests__/graphics.spec.ts @@ -1,4 +1,4 @@ -import { IBlueprintRundownDB, PieceLifespan, PlaylistTimingType, TSR } from '@tv2media/blueprints-integration' +import { IBlueprintRundownDB, PieceLifespan, PlaylistTimingType, TSR } from 'blueprints-integration' import { CueDefinition, CueDefinitionBackgroundLoop, @@ -224,7 +224,7 @@ describe('Graphics', () => { t.content.deviceType === TSR.DeviceType.VIZMSE && t.content.type === TSR.TimelineContentTypeVizMSE.ELEMENT_PILOT )! as TSR.TimelineObjVIZMSEElementPilot expect(vizObj.enable).toEqual({ while: '!.full' }) - expect(vizObj.layer).toEqual(SharedGraphicLLayer.GraphicLLayerPilotOverlay) + expect(vizObj.layer).toEqual(SharedGraphicLLayer.GraphicLLayerOverlayPilot) expect(vizObj.content.channelName).toBe('OVL1') // TODO: OVL1: Enum / Type expect(vizObj.content.templateVcpId).toBe(1234567890) expect(vizObj.content.continueStep).toBe(-1) diff --git a/src/tv2_afvd_studio/config-manifests.ts b/src/tv2_afvd_studio/config-manifests.ts index 9998bbe39..ad8217036 100644 --- a/src/tv2_afvd_studio/config-manifests.ts +++ b/src/tv2_afvd_studio/config-manifests.ts @@ -4,7 +4,7 @@ import { ConfigManifestEntryType, TableConfigItemValue, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { DSKConfigManifest, literal, @@ -436,8 +436,8 @@ export const studioConfigManifest: ConfigManifestEntry[] = [ }, { id: 'HTMLGraphics.GraphicURL', - name: 'Full Graphic URL (HTML)', - description: 'URL to serve full graphics from', + name: 'Pilot Graphic URL (HTML)', + description: 'URL to serve prerendered full/overlay images from', type: ConfigManifestEntryType.STRING, required: false, defaultVal: 'localhost' diff --git a/src/tv2_afvd_studio/getBaseline.ts b/src/tv2_afvd_studio/getBaseline.ts index 96220025b..b35656ba0 100644 --- a/src/tv2_afvd_studio/getBaseline.ts +++ b/src/tv2_afvd_studio/getBaseline.ts @@ -4,7 +4,7 @@ import { BlueprintResultBaseline, IStudioContext, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal } from 'tv2-common' import * as _ from 'underscore' import { SharedGraphicLLayer } from '../tv2-constants' diff --git a/src/tv2_afvd_studio/getShowStyleId.ts b/src/tv2_afvd_studio/getShowStyleId.ts index 1c2406d12..d23f72b94 100644 --- a/src/tv2_afvd_studio/getShowStyleId.ts +++ b/src/tv2_afvd_studio/getShowStyleId.ts @@ -1,4 +1,4 @@ -import { IBlueprintShowStyleBase, IngestRundown, IStudioContext } from '@tv2media/blueprints-integration' +import { IBlueprintShowStyleBase, IngestRundown, IStudioContext } from 'blueprints-integration' import * as _ from 'underscore' export function getShowStyleId( diff --git a/src/tv2_afvd_studio/helpers/config.ts b/src/tv2_afvd_studio/helpers/config.ts index 2eb9c2028..40e26ef23 100644 --- a/src/tv2_afvd_studio/helpers/config.ts +++ b/src/tv2_afvd_studio/helpers/config.ts @@ -1,4 +1,4 @@ -import { IBlueprintConfig, ICommonContext, IStudioContext } from '@tv2media/blueprints-integration' +import { IBlueprintConfig, ICommonContext, IStudioContext } from 'blueprints-integration' import { MediaPlayerConfig, SourceMapping, diff --git a/src/tv2_afvd_studio/helpers/sources.ts b/src/tv2_afvd_studio/helpers/sources.ts index dd5edeb23..2642894e7 100644 --- a/src/tv2_afvd_studio/helpers/sources.ts +++ b/src/tv2_afvd_studio/helpers/sources.ts @@ -1,6 +1,6 @@ import * as _ from 'underscore' -import { SourceLayerType } from '@tv2media/blueprints-integration' +import { SourceLayerType } from 'blueprints-integration' import { ParseMappingTable, SourceInfoType, SourceMapping } from 'tv2-common' import { StudioConfig } from './config' diff --git a/src/tv2_afvd_studio/index.ts b/src/tv2_afvd_studio/index.ts index 2c5ad9b55..9b2775df0 100644 --- a/src/tv2_afvd_studio/index.ts +++ b/src/tv2_afvd_studio/index.ts @@ -1,4 +1,4 @@ -import { BlueprintManifestType, StudioBlueprintManifest } from '@tv2media/blueprints-integration' +import { BlueprintManifestType, StudioBlueprintManifest } from 'blueprints-integration' import { GetStudioManifestWithMixins, StudioManifestMixinINews } from 'inews-mixins' import * as _ from 'underscore' import { studioConfigManifest } from './config-manifests' diff --git a/src/tv2_afvd_studio/layers.ts b/src/tv2_afvd_studio/layers.ts index da63cf864..de316adb3 100644 --- a/src/tv2_afvd_studio/layers.ts +++ b/src/tv2_afvd_studio/layers.ts @@ -1,5 +1,6 @@ import { AbstractLLayer, + RobotCameraLayer, SharedATEMLLayer, SharedCasparLLayer, SharedGraphicLLayer, @@ -23,6 +24,8 @@ export function RealLLayers(): string[] { .concat(_.values(GraphicLLayer)) // @ts-ignore .concat(_.values(VirtualAbstractLLayer)) + // @ts-ignore + .concat(_.values(RobotCameraLayer)) ) } diff --git a/src/tv2_afvd_studio/migrations/devices.ts b/src/tv2_afvd_studio/migrations/devices.ts index ae375657d..dbf81e312 100644 --- a/src/tv2_afvd_studio/migrations/devices.ts +++ b/src/tv2_afvd_studio/migrations/devices.ts @@ -4,7 +4,7 @@ import { MigrationStepInputFilteredResult, MigrationStepStudio, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import * as _ from 'underscore' declare const VERSION: string // Injected by webpack diff --git a/src/tv2_afvd_studio/migrations/index.ts b/src/tv2_afvd_studio/migrations/index.ts index 421ec2d1a..0428d9fd4 100644 --- a/src/tv2_afvd_studio/migrations/index.ts +++ b/src/tv2_afvd_studio/migrations/index.ts @@ -1,4 +1,4 @@ -import { MigrationStepStudio, TSR } from '@tv2media/blueprints-integration' +import { MigrationStepStudio, TSR } from 'blueprints-integration' import { AddKeepAudio, addSourceToSourcesConfig, @@ -195,6 +195,12 @@ export const studioMigrations: MigrationStepStudio[] = [ PrefixEvsWithEvs('1.7.4', 'AFVD', 'SourcesReplay', '1'), PrefixEvsWithEvs('1.7.4', 'AFVD', 'SourcesReplay', '2'), + /** + * 1.7.8 + * - Rename the GraphicLLayerPilotOverlay, because alphabetical order matters for deeply extending the Caspar Objects targeting the same channel:layer + */ + renameMapping('1.7.8', 'graphic_pilot_overlay', 'graphic_overlay_pilot'), + // Fill in any mappings 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 ...getMappingsDefaultsMigrationSteps(VERSION) diff --git a/src/tv2_afvd_studio/migrations/mappings-defaults.ts b/src/tv2_afvd_studio/migrations/mappings-defaults.ts index 61de850b3..fa3b59bb3 100644 --- a/src/tv2_afvd_studio/migrations/mappings-defaults.ts +++ b/src/tv2_afvd_studio/migrations/mappings-defaults.ts @@ -1,4 +1,4 @@ -import { BlueprintMapping, BlueprintMappings, LookaheadMode, TSR } from '@tv2media/blueprints-integration' +import { BlueprintMapping, BlueprintMappings, LookaheadMode, TSR } from 'blueprints-integration' import { AbstractLLayerServerEnable, CasparPlayerClip, @@ -7,7 +7,7 @@ import { literal, SisyfosPlayerClip } from 'tv2-common' -import { AbstractLLayer } from 'tv2-constants' +import { AbstractLLayer, RobotCameraLayer } from 'tv2-constants' import { ATEMModel } from '../../types/atem' import { BlueprintConfig } from '../helpers/config' import { AtemLLayer, CasparLLayer, GraphicLLayer, SisyfosLLAyer } from '../layers' @@ -515,7 +515,7 @@ export const MAPPINGS_GRAPHICS: BlueprintMappings = { layerName: 'GFX Pilot (Full)', lookahead: LookaheadMode.NONE }), - [GraphicLLayer.GraphicLLayerPilotOverlay]: literal({ + [GraphicLLayer.GraphicLLayerOverlayPilot]: literal({ device: TSR.DeviceType.VIZMSE, deviceId: 'viz0', layerName: 'GFX Pilot (Overlay)', @@ -713,12 +713,21 @@ export const MAPPINGS_ATEM: BlueprintMappings = { }) } +export const MAPPINGS_TELEMETRICS: BlueprintMappings = { + [RobotCameraLayer.TELEMETRICS]: literal({ + device: TSR.DeviceType.TELEMETRICS, + deviceId: 'telemetrics0', + lookahead: LookaheadMode.NONE + }) +} + export default literal({ ...MAPPINGS_ABSTRACT, ...MAPPINGS_SISYFOS, ...MAPPINGS_CASPAR, ...MAPPINGS_GRAPHICS, - ...MAPPINGS_ATEM + ...MAPPINGS_ATEM, + ...MAPPINGS_TELEMETRICS }) export function getMediaPlayerMappings(mediaPlayers: BlueprintConfig['mediaPlayers']) { diff --git a/src/tv2_afvd_studio/migrations/util.ts b/src/tv2_afvd_studio/migrations/util.ts index c3e270763..a1d9a7043 100644 --- a/src/tv2_afvd_studio/migrations/util.ts +++ b/src/tv2_afvd_studio/migrations/util.ts @@ -6,7 +6,7 @@ import { MigrationStepInputFilteredResult, MigrationStepStudio, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import * as _ from 'underscore' import { SisyfosLLAyer } from '../layers' import MappingsDefaults from './mappings-defaults' diff --git a/src/tv2_afvd_studio/onTimelineGenerate.ts b/src/tv2_afvd_studio/onTimelineGenerate.ts index 0cbd50c4a..527c80979 100644 --- a/src/tv2_afvd_studio/onTimelineGenerate.ts +++ b/src/tv2_afvd_studio/onTimelineGenerate.ts @@ -5,7 +5,7 @@ import { OnGenerateTimelineObj, PartEndState, TimelinePersistentState -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { onTimelineGenerate, PieceMetaData } from 'tv2-common' import { getConfig } from '../tv2_afvd_showstyle/helpers/config' import { AtemLLayer, CasparLLayer, SisyfosLLAyer } from './layers' diff --git a/src/tv2_offtube_showstyle/__tests__/actions.spec.ts b/src/tv2_offtube_showstyle/__tests__/actions.spec.ts index 4714696ff..55330e275 100644 --- a/src/tv2_offtube_showstyle/__tests__/actions.spec.ts +++ b/src/tv2_offtube_showstyle/__tests__/actions.spec.ts @@ -4,7 +4,7 @@ import { IBlueprintPieceInstance, PieceLifespan, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionCommentatorSelectDVE, ActionCutToCamera, @@ -198,6 +198,7 @@ const selectDVEActionMorbarn = literal({ labels: ['Live'], iNewsCommand: 'DVE=MORBARN' }, + name: 'morbarn', videoId: undefined, segmentExternalId: SEGMENT_ID_EXTERNAL }) @@ -214,6 +215,7 @@ const selectDVEActionBarnmor = literal({ labels: ['Live'], iNewsCommand: 'DVE=BARNMOR' }, + name: 'barnmor', videoId: undefined, segmentExternalId: SEGMENT_ID_EXTERNAL }) diff --git a/src/tv2_offtube_showstyle/__tests__/config-manifest.spec.ts b/src/tv2_offtube_showstyle/__tests__/config-manifest.spec.ts index f162b4cf0..4e3a81e19 100644 --- a/src/tv2_offtube_showstyle/__tests__/config-manifest.spec.ts +++ b/src/tv2_offtube_showstyle/__tests__/config-manifest.spec.ts @@ -5,6 +5,7 @@ import { OfftubeShowStyleConfig } from '../helpers/config' const blankShowStyleConfig: OfftubeShowStyleConfig = { DVEStyles: [], GFXTemplates: [], + GfxDesignTemplates: [], WipesConfig: [], BreakerConfig: [], DefaultTemplateDuration: 4, @@ -13,7 +14,9 @@ const blankShowStyleConfig: OfftubeShowStyleConfig = { Transitions: [{ Transition: '1' }, { Transition: '2' }], ShowstyleTransition: 'CUT', MakeAdlibsForFulls: true, - SchemaConfig: [] + GfxSchemaTemplates: [], + GraphicsSetups: [], + SelectedGraphicsSetupName: '' } describe('Config Manifest', () => { diff --git a/src/tv2_offtube_showstyle/actions.ts b/src/tv2_offtube_showstyle/actions.ts index 5c662c342..674351e8f 100644 --- a/src/tv2_offtube_showstyle/actions.ts +++ b/src/tv2_offtube_showstyle/actions.ts @@ -1,4 +1,4 @@ -import { ActionUserData, IActionExecutionContext } from '@tv2media/blueprints-integration' +import { ActionUserData, IActionExecutionContext } from 'blueprints-integration' import { executeAction } from 'tv2-common' import { OfftubeAtemLLayer, OfftubeCasparLLayer, OfftubeSisyfosLLayer } from '../tv2_offtube_studio/layers' import { OFFTUBE_DVE_GENERATOR_OPTIONS } from './content/OfftubeDVEContent' diff --git a/src/tv2_offtube_showstyle/config-manifests.ts b/src/tv2_offtube_showstyle/config-manifests.ts index 662fc68a0..1fb3308ec 100644 --- a/src/tv2_offtube_showstyle/config-manifests.ts +++ b/src/tv2_offtube_showstyle/config-manifests.ts @@ -1,5 +1,5 @@ -import { ConfigManifestEntry, ConfigManifestEntryType, TSR } from '@tv2media/blueprints-integration' -import { DEFAULT_GRAPHICS } from 'tv2-common' +import { ConfigManifestEntry, ConfigManifestEntryType, TSR } from 'blueprints-integration' +import { DEFAULT_GRAPHICS, getGraphicsSetupsEntries } from 'tv2-common' export const dveStylesManifest: ConfigManifestEntry = { id: 'DVEStyles', @@ -142,6 +142,92 @@ export const dveStylesManifest: ConfigManifestEntry = { ] } +const DESIGN_TABLE_ID = 'GfxDesignTemplates' +const DESIGN_NAME_COLUMN_ID = 'INewsName' + +export const gfxDesignTemplates: ConfigManifestEntry[] = [ + { + id: DESIGN_TABLE_ID, + name: 'GFX Design Templates', + description: '', + type: ConfigManifestEntryType.TABLE, + required: true, + defaultVal: DEFAULT_GRAPHICS.map(val => ({ _id: '', ...val })).filter(template => template.IsDesign), + columns: [ + { + id: DESIGN_NAME_COLUMN_ID, + name: 'iNews Name', + description: 'The name of the design', + type: ConfigManifestEntryType.STRING, + required: false, + defaultVal: '', + rank: 0 + }, + { + id: 'INewsStyleColumn', + name: 'iNews Style Column', + description: 'The selected style', + type: ConfigManifestEntryType.STRING, + required: false, + defaultVal: '', + rank: 1 + }, + { + id: 'VizTemplate', + name: 'GFX Template Name', + description: 'The name of the design in the HTML package', + type: ConfigManifestEntryType.STRING, + required: true, + defaultVal: '', + rank: 2 + } + ] + } +] + +const GFX_SCHEMA_TABLE_ID = 'GfxSchemaTemplates' +const GFX_SCHEMA_NAME_COLUMN_ID = 'GfxSchemaTemplatesName' + +export const gfxSchemaTemplates: ConfigManifestEntry[] = [ + { + id: GFX_SCHEMA_TABLE_ID, + name: 'GFX Skema Templates', + description: 'The values for the Skema and Design combinations', + type: ConfigManifestEntryType.TABLE, + required: false, + defaultVal: [], + columns: [ + { + id: GFX_SCHEMA_NAME_COLUMN_ID, + name: 'iNews Name', + description: 'The name of the design', + type: ConfigManifestEntryType.STRING, + required: false, + defaultVal: '', + rank: 0 + }, + { + id: 'INewsSkemaColumn', + name: 'iNews Skema Column', + description: 'The selected skema', + type: ConfigManifestEntryType.STRING, + required: false, + defaultVal: '', + rank: 1 + }, + { + id: 'VizTemplate', + name: 'GFX Template Name', + description: 'For future asset control', + type: ConfigManifestEntryType.STRING, + required: true, + defaultVal: '', + rank: 2 + } + ] + } +] + export const showStyleConfigManifest: ConfigManifestEntry[] = [ { id: 'MakeAdlibsForFulls', @@ -176,10 +262,10 @@ export const showStyleConfigManifest: ConfigManifestEntry[] = [ id: 'GFXTemplates', name: 'GFX Templates', description: - 'This table can contain info in two ways. Things marked (**) are always required. If you want to do the mapping from iNews-code, then all (*)-elements are aslo required. VizTemplate is what the graphic is called in viz. Source layer is the ID of the Sofie Source layer in the UI (i.e. "studio0_graphicsTema"). Layer mapping is the Sofie studio layer mapping (i.e "viz_layer_tema"). iNews command can be something like "KG=", then iNews Name is the thing that follows in iNes i.e. "ident_nyhederne"', + 'This table can contain info in two ways. Things marked (**) are always required. If you want to do the mapping from iNews-code, then all (*)-elements are also required. GFX Template Name is what the graphic is called in the HTML package. Source layer is the ID of the Sofie Source layer in the UI (i.e. "studio0_graphicsTema"). Layer mapping is the Sofie studio layer mapping (i.e "viz_layer_tema"). iNews command can be something like "KG=", then iNews Name is the thing that follows in iNews i.e. "ident_nyhederne"', type: ConfigManifestEntryType.TABLE, required: false, - defaultVal: DEFAULT_GRAPHICS.map(val => ({ _id: '', ...val })), + defaultVal: DEFAULT_GRAPHICS.map(val => ({ _id: '', ...val })).filter(template => !template.IsDesign), columns: [ { id: 'INewsCode', @@ -201,8 +287,8 @@ export const showStyleConfigManifest: ConfigManifestEntry[] = [ }, { id: 'VizTemplate', - name: 'Viz Template Name (**)', - description: 'The name of the Viz Template', + name: 'GFX Template Name (**)', + description: 'The name of the Graphic in the HTML package', type: ConfigManifestEntryType.STRING, required: true, defaultVal: '', @@ -226,15 +312,6 @@ export const showStyleConfigManifest: ConfigManifestEntry[] = [ defaultVal: '', rank: 4 }, - { - id: 'IsDesign', - name: 'Changes Design', - description: 'Whether this cue changes the design', - type: ConfigManifestEntryType.BOOLEAN, - required: false, - defaultVal: false, - rank: 5 - }, { id: 'SourceLayer', name: 'Source layer (**)', @@ -261,6 +338,7 @@ export const showStyleConfigManifest: ConfigManifestEntry[] = [ } ] }, + ...gfxDesignTemplates, { /* Wipes Config @@ -516,50 +594,6 @@ export const showStyleConfigManifest: ConfigManifestEntry[] = [ } ] }, - { - id: 'SchemaConfig', - name: 'Skema', - description: 'The values for the Skema and Design combinations', - type: ConfigManifestEntryType.TABLE, - required: false, - defaultVal: [], - columns: [ - { - id: 'schemaName', - name: 'Skema', - description: 'The name of the Skema', - rank: 0, - required: true, - defaultVal: '', - type: ConfigManifestEntryType.STRING - }, - { - id: 'designIdentifier', - name: 'Design', - description: 'The identifier of the Design', - rank: 1, - required: true, - defaultVal: '', - type: ConfigManifestEntryType.STRING - }, - { - id: 'vizTemplateName', - name: 'Viz Template Name', - description: 'The name of the Viz template', - rank: 2, - required: true, - defaultVal: '', - type: ConfigManifestEntryType.STRING - }, - { - id: 'casparCgDveBgScene', - name: 'CasparCG DVE Bg Scene', - description: 'The dveBgScene', - defaultVal: '', - rank: 3, - required: true, - type: ConfigManifestEntryType.STRING - } - ] - } + ...gfxSchemaTemplates, + ...getGraphicsSetupsEntries([]) ] diff --git a/src/tv2_offtube_showstyle/content/OfftubeDVEContent.ts b/src/tv2_offtube_showstyle/content/OfftubeDVEContent.ts index 8996e0054..f1140b91c 100644 --- a/src/tv2_offtube_showstyle/content/OfftubeDVEContent.ts +++ b/src/tv2_offtube_showstyle/content/OfftubeDVEContent.ts @@ -1,4 +1,4 @@ -import { ISegmentUserContext, SplitsContent, WithTimeline } from '@tv2media/blueprints-integration' +import { ISegmentUserContext, SplitsContent, WithTimeline } from 'blueprints-integration' import { CueDefinitionDVE, DVEConfigInput, DVEOptions, MakeContentDVEBase, PartDefinition } from 'tv2-common' import { OfftubeAtemLLayer, OfftubeCasparLLayer, OfftubeSisyfosLLayer } from '../../tv2_offtube_studio/layers' import { OfftubeShowstyleBlueprintConfig } from '../helpers/config' @@ -40,18 +40,7 @@ export function OfftubeMakeContentDVE( config: OfftubeShowstyleBlueprintConfig, partDefinition: PartDefinition, parsedCue: CueDefinitionDVE, - dveConfig: DVEConfigInput | undefined, - addClass?: boolean, - adlib?: boolean + dveConfig: DVEConfigInput | undefined ): { content: WithTimeline; valid: boolean } { - return MakeContentDVEBase( - context, - config, - partDefinition, - parsedCue, - dveConfig, - OFFTUBE_DVE_GENERATOR_OPTIONS, - addClass, - adlib - ) + return MakeContentDVEBase(context, config, partDefinition, parsedCue, dveConfig, OFFTUBE_DVE_GENERATOR_OPTIONS) } diff --git a/src/tv2_offtube_showstyle/cues/OfftubeAdlib.ts b/src/tv2_offtube_showstyle/cues/OfftubeAdlib.ts index c3e76dd71..723dd5843 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeAdlib.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeAdlib.ts @@ -1,12 +1,11 @@ import { HackPartMediaObjectSubscription, IBlueprintActionManifest, - IBlueprintAdLibPiece, ISegmentUserContext, SplitsContent, TimelineObjectCoreExt, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionSelectDVE, CreateAdlibServer, @@ -30,10 +29,8 @@ import { OfftubeOutputLayers, OfftubeSourceLayer } from '../layers' export async function OfftubeEvaluateAdLib( context: ISegmentUserContext, config: OfftubeShowstyleBlueprintConfig, - _adLibPieces: IBlueprintAdLibPiece[], actions: IBlueprintActionManifest[], mediaSubscriptions: HackPartMediaObjectSubscription[], - _partId: string, parsedCue: CueDefinitionAdLib, partDefinition: PartDefinition, rank: number @@ -103,11 +100,12 @@ export async function OfftubeEvaluateAdLib( iNewsCommand: 'DVE' } - const adlibContent = OfftubeMakeContentDVE(context, config, partDefinition, cueDVE, rawTemplate, false, true) + const adlibContent = OfftubeMakeContentDVE(context, config, partDefinition, cueDVE, rawTemplate) const userData: ActionSelectDVE = { type: AdlibActionType.SELECT_DVE, config: cueDVE, + name: `DVE: ${cueDVE.template}`, videoId: partDefinition.fields.videoId, segmentExternalId: partDefinition.segmentExternalId } diff --git a/src/tv2_offtube_showstyle/cues/OfftubeDVE.ts b/src/tv2_offtube_showstyle/cues/OfftubeDVE.ts index 0f0501234..8d76aef8b 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeDVE.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeDVE.ts @@ -1,14 +1,12 @@ import { IBlueprintActionManifest, - IBlueprintAdLibPiece, IBlueprintPiece, ISegmentUserContext, PieceLifespan, SplitsContent -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionSelectDVE, - AddParentClass, CalculateTime, CueDefinitionDVE, DVEPieceMetaData, @@ -30,7 +28,6 @@ export function OfftubeEvaluateDVE( context: ISegmentUserContext, config: OfftubeShowstyleBlueprintConfig, pieces: IBlueprintPiece[], - _adlibPieces: IBlueprintAdLibPiece[], actions: IBlueprintActionManifest[], partDefinition: PartDefinition, parsedCue: CueDefinitionDVE, @@ -52,25 +49,9 @@ export function OfftubeEvaluateDVE( return } - const adlibContent = OfftubeMakeContentDVE( - context, - config, - partDefinition, - parsedCue, - rawTemplate, - AddParentClass(config, partDefinition), - true - ) + const adlibContent = OfftubeMakeContentDVE(context, config, partDefinition, parsedCue, rawTemplate) - const pieceContent = OfftubeMakeContentDVE( - context, - config, - partDefinition, - parsedCue, - rawTemplate, - AddParentClass(config, partDefinition), - false - ) + const pieceContent = OfftubeMakeContentDVE(context, config, partDefinition, parsedCue, rawTemplate) if (adlibContent.valid && pieceContent.valid) { let start = parsedCue.start ? CalculateTime(parsedCue.start) : 0 @@ -78,7 +59,7 @@ export function OfftubeEvaluateDVE( const end = parsedCue.end ? CalculateTime(parsedCue.end) : undefined pieces.push({ externalId: partDefinition.externalId, - name: `${parsedCue.template}`, + name: parsedCue.template, enable: { start, ...(end ? { duration: end - start } : {}) @@ -99,6 +80,7 @@ export function OfftubeEvaluateDVE( userData: { type: AdlibActionType.SELECT_DVE, config: parsedCue, + name: parsedCue.template, videoId: partDefinition.fields.videoId, segmentExternalId: partDefinition.segmentExternalId }, @@ -116,6 +98,7 @@ export function OfftubeEvaluateDVE( const userData: ActionSelectDVE = { type: AdlibActionType.SELECT_DVE, config: parsedCue, + name: `DVE: ${parsedCue.template}`, videoId: partDefinition.fields.videoId, segmentExternalId: partDefinition.segmentExternalId } diff --git a/src/tv2_offtube_showstyle/cues/OfftubeEkstern.ts b/src/tv2_offtube_showstyle/cues/OfftubeEkstern.ts index 1164e20a3..687fe761c 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeEkstern.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeEkstern.ts @@ -4,7 +4,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CueDefinitionEkstern, EvaluateEksternBase, PartDefinition, PieceMetaData } from 'tv2-common' import { OfftubeAtemLLayer } from '../../tv2_offtube_studio/layers' import { OfftubeShowstyleBlueprintConfig } from '../helpers/config' diff --git a/src/tv2_offtube_showstyle/cues/OfftubeGraphicBackgroundLoop.ts b/src/tv2_offtube_showstyle/cues/OfftubeGraphicBackgroundLoop.ts index 2277c7248..5fcd29568 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeGraphicBackgroundLoop.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeGraphicBackgroundLoop.ts @@ -6,7 +6,7 @@ import { PieceLifespan, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CalculateTime, CueDefinitionBackgroundLoop, literal, TV2BlueprintConfig } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' import _ = require('underscore') diff --git a/src/tv2_offtube_showstyle/cues/OfftubeGraphicDesign.ts b/src/tv2_offtube_showstyle/cues/OfftubeGraphicDesign.ts index f524c7418..278f38edc 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeGraphicDesign.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeGraphicDesign.ts @@ -3,7 +3,7 @@ import { IBlueprintAdLibPiece, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CueDefinitionGraphicDesign, EvaluateDesignBase } from 'tv2-common' import { OfftubeShowstyleBlueprintConfig } from '../helpers/config' diff --git a/src/tv2_offtube_showstyle/cues/OfftubeGraphics.ts b/src/tv2_offtube_showstyle/cues/OfftubeGraphics.ts index c09058e76..b1894a09d 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeGraphics.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeGraphics.ts @@ -4,7 +4,7 @@ import { IBlueprintPiece, IShowStyleUserContext, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { Adlib, CreateInternalGraphic, @@ -24,10 +24,10 @@ import { OfftubeShowstyleBlueprintConfig } from '../helpers/config' export const pilotGeneratorSettingsOfftube: PilotGeneratorSettings = { caspar: { - createPilotTimelineForStudio: createPilotTimeline + createFullPilotTimelineForStudio: createPilotTimeline }, viz: { - createPilotTimelineForStudio: () => [] + createFullPilotTimelineForStudio: () => [] } } @@ -44,7 +44,6 @@ export function OfftubeEvaluateGrafikCaspar( ) { if (GraphicIsPilot(parsedCue)) { CreatePilotGraphic(pieces, adlibPieces, actions, { - engine: parsedCue.target, config, context, partId, @@ -58,10 +57,7 @@ export function OfftubeEvaluateGrafikCaspar( } } -function createPilotTimeline( - config: OfftubeShowstyleBlueprintConfig, - _context: IShowStyleUserContext -): TSR.TSRTimelineObj[] { +function createPilotTimeline(config: OfftubeShowstyleBlueprintConfig): TSR.TSRTimelineObj[] { const fullDSK = FindDSKFullGFX(config) return [ literal({ diff --git a/src/tv2_offtube_showstyle/cues/OfftubeJingle.ts b/src/tv2_offtube_showstyle/cues/OfftubeJingle.ts index f82cd7ba6..f5fc5ec25 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubeJingle.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubeJingle.ts @@ -4,7 +4,7 @@ import { IBlueprintPiece, ISegmentUserContext, PieceLifespan -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionSelectJingle, CreateJingleContentBase, diff --git a/src/tv2_offtube_showstyle/cues/OfftubePgmClean.ts b/src/tv2_offtube_showstyle/cues/OfftubePgmClean.ts index b54b086d4..bd152146d 100644 --- a/src/tv2_offtube_showstyle/cues/OfftubePgmClean.ts +++ b/src/tv2_offtube_showstyle/cues/OfftubePgmClean.ts @@ -6,7 +6,7 @@ import { TimelineObjectCoreExt, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CueDefinitionPgmClean, findSourceInfo, literal, SourceInfo } from 'tv2-common' import { SharedOutputLayers, SourceType } from 'tv2-constants' import { OfftubeAtemLLayer } from '../../tv2_offtube_studio/layers' diff --git a/src/tv2_offtube_showstyle/getRundown.ts b/src/tv2_offtube_showstyle/getRundown.ts index 209a92cba..3ec174b10 100644 --- a/src/tv2_offtube_showstyle/getRundown.ts +++ b/src/tv2_offtube_showstyle/getRundown.ts @@ -10,7 +10,7 @@ import { PieceLifespan, PlaylistTimingType, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { ActionClearGraphics, ActionCommentatorSelectDVE, diff --git a/src/tv2_offtube_showstyle/getSegment.ts b/src/tv2_offtube_showstyle/getSegment.ts index eedba6e0c..4b8167bf1 100644 --- a/src/tv2_offtube_showstyle/getSegment.ts +++ b/src/tv2_offtube_showstyle/getSegment.ts @@ -7,7 +7,7 @@ import { PieceLifespan, TSR, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { getSegmentBase, literal } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' import * as _ from 'underscore' diff --git a/src/tv2_offtube_showstyle/helpers/EvaluateCues.ts b/src/tv2_offtube_showstyle/helpers/EvaluateCues.ts index 1744b59d3..ff522c375 100644 --- a/src/tv2_offtube_showstyle/helpers/EvaluateCues.ts +++ b/src/tv2_offtube_showstyle/helpers/EvaluateCues.ts @@ -5,7 +5,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { CueDefinition, EvaluateCuesBase, EvaluateCuesOptions, EvaluateLYD, PartDefinition } from 'tv2-common' import { OfftubeEvaluateAdLib } from '../cues/OfftubeAdlib' import { OfftubeEvaluateDVE } from '../cues/OfftubeDVE' diff --git a/src/tv2_offtube_showstyle/helpers/config.ts b/src/tv2_offtube_showstyle/helpers/config.ts index 3ad8906ad..df3d65a69 100644 --- a/src/tv2_offtube_showstyle/helpers/config.ts +++ b/src/tv2_offtube_showstyle/helpers/config.ts @@ -4,12 +4,12 @@ import { IShowStyleContext, IStudioContext, TableConfigItemValue -} from '@tv2media/blueprints-integration' -import { TableConfigGraphicsSetup, TV2ShowstyleBlueprintConfigBase } from 'tv2-common' +} from 'blueprints-integration' +import { findGraphicsSetup, TableConfigGraphicsSetup, TV2ShowstyleBlueprintConfigBase } from 'tv2-common' import * as _ from 'underscore' import { OfftubeStudioBlueprintConfig } from '../../tv2_offtube_studio/helpers/config' -export interface TableConfigItemGFXTemplates { +export interface TableConfigItemGfxTemplates { VizTemplate: string SourceLayer: string LayerMapping: string @@ -36,25 +36,15 @@ export interface DVEConfigInput { export interface OfftubeShowStyleConfig extends TV2ShowstyleBlueprintConfigBase { WipesConfig: TableConfigItemValue -} - -function findGraphicsSetup( - _context: ICommonContext, - _config: TV2ShowstyleBlueprintConfigBase -): TableConfigGraphicsSetup { - // just for type compatibility, not really supported in offtube - return { - Name: '', - VcpConcept: '', - OvlShowId: '', - FullShowId: '', - DveLayoutFolder: '' - } + GraphicsSetups: TableConfigGraphicsSetup[] } export function parseConfig(context: ICommonContext, rawConfig: IBlueprintConfig): any { const showstyleConfig = (rawConfig as unknown) as OfftubeShowStyleConfig - const selectedGraphicsSetup = findGraphicsSetup(context, showstyleConfig) + const selectedGraphicsSetup = findGraphicsSetup(context, showstyleConfig, { + Name: '', + HtmlPackageFolder: '' + }) return { showStyle: showstyleConfig, selectedGraphicsSetup diff --git a/src/tv2_offtube_showstyle/index.ts b/src/tv2_offtube_showstyle/index.ts index e6aba71e8..800ebb8db 100644 --- a/src/tv2_offtube_showstyle/index.ts +++ b/src/tv2_offtube_showstyle/index.ts @@ -1,10 +1,9 @@ -import { BlueprintManifestType, ShowStyleBlueprintManifest } from '@tv2media/blueprints-integration' -import { getShowStyleVariantId } from '../tv2-common/getShowStyleVariantId' +import { BlueprintManifestType, ShowStyleBlueprintManifest } from 'blueprints-integration' import { showStyleConfigManifest } from './config-manifests' import { showStyleMigrations } from './migrations' import { GetShowStyleManifestWithMixins, ShowStyleManifestMixinINews } from 'inews-mixins' -import { getEndStateForPart } from 'tv2-common' +import { getEndStateForPart, getShowStyleVariantId } from 'tv2-common' import { onTimelineGenerateOfftube } from '../tv2_offtube_showstyle/onTimelineGenerate' import { executeActionOfftube } from './actions' import { getRundown } from './getRundown' diff --git a/src/tv2_offtube_showstyle/migrations/hotkeys.ts b/src/tv2_offtube_showstyle/migrations/hotkeys.ts index 52a07d7fe..25c7771b0 100644 --- a/src/tv2_offtube_showstyle/migrations/hotkeys.ts +++ b/src/tv2_offtube_showstyle/migrations/hotkeys.ts @@ -1,8 +1,4 @@ -import { - ConfigManifestEntryTable, - MigrationContextShowStyle, - TableConfigItemValue -} from '@tv2media/blueprints-integration' +import { ConfigManifestEntryTable, MigrationContextShowStyle, TableConfigItemValue } from 'blueprints-integration' import { GlobalHotkeySources } from 'tv2-common' import { manifestOfftubeSourcesCam, diff --git a/src/tv2_offtube_showstyle/migrations/index.ts b/src/tv2_offtube_showstyle/migrations/index.ts index 9ca3d320d..7153ae468 100644 --- a/src/tv2_offtube_showstyle/migrations/index.ts +++ b/src/tv2_offtube_showstyle/migrations/index.ts @@ -1,9 +1,10 @@ -import { MigrationStepShowStyle, SourceLayerType } from '@tv2media/blueprints-integration' +import { MigrationStepShowStyle, SourceLayerType } from 'blueprints-integration' import { - AddGraphicToGFXTable, - changeGFXTemplate, + AddGraphicToGfxTable, + changeGfxTemplate, GetDefaultAdLibTriggers, GetDSKSourceLayerNames, + mapGfxTemplateToDesignTemplateAndDeleteOriginals, RemoveOldShortcuts, removeSourceLayer, renameSourceLayer, @@ -54,7 +55,7 @@ export const remapVizLLayer: Map = new Map([ [VizLLayer.VizLLayerOverlayHeadline, SharedGraphicLLayer.GraphicLLayerOverlayHeadline], [VizLLayer.VizLLayerOverlayTema, SharedGraphicLLayer.GraphicLLayerOverlayTema], [VizLLayer.VizLLayerPilot, SharedGraphicLLayer.GraphicLLayerPilot], - [VizLLayer.VizLLayerPilotOverlay, SharedGraphicLLayer.GraphicLLayerPilotOverlay], + [VizLLayer.VizLLayerPilotOverlay, SharedGraphicLLayer.GraphicLLayerOverlayPilot], [VizLLayer.VizLLayerDesign, SharedGraphicLLayer.GraphicLLayerDesign], [VizLLayer.VizLLayerAdLibs, SharedGraphicLLayer.GraphicLLayerAdLibs], [VizLLayer.VizLLayerWall, SharedGraphicLLayer.GraphicLLayerWall] @@ -73,7 +74,7 @@ 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(), - ...remapTableColumnValues('0.1.0', 'GFXTemplates', 'LayerMapping', remapVizLLayer), + remapTableColumnValues('0.1.0', 'GFXTemplates', 'LayerMapping', remapVizLLayer), ...getSourceLayerDefaultsMigrationSteps('1.3.0', true), /** @@ -115,7 +116,7 @@ export const showStyleMigrations: MigrationStepShowStyle[] = [ */ forceSourceLayerToDefaults('1.5.2', OfftubeSourceLayer.PgmJingle), - AddGraphicToGFXTable('1.5.4', 'Offtube', { + AddGraphicToGfxTable('1.5.4', 'Offtube', { VizTemplate: 'locators', SourceLayer: '', LayerMapping: SharedGraphicLLayer.GraphicLLayerLocators, @@ -223,7 +224,7 @@ export const showStyleMigrations: MigrationStepShowStyle[] = [ * 1.7.2 * - Fix bundright configuration */ - changeGFXTemplate( + changeGfxTemplate( '1.7.2', 'QBOX', { @@ -235,7 +236,7 @@ export const showStyleMigrations: MigrationStepShowStyle[] = [ }, { OutType: '' } ), - changeGFXTemplate( + changeGfxTemplate( '1.7.2', 'QBOX', { @@ -247,7 +248,7 @@ export const showStyleMigrations: MigrationStepShowStyle[] = [ }, { SourceLayer: 'studio0_graphicsLower' } ), - changeGFXTemplate( + changeGfxTemplate( '1.7.2', 'QBOX', { @@ -266,6 +267,20 @@ export const showStyleMigrations: MigrationStepShowStyle[] = [ */ removeSourceLayer('1.7.5', 'AFVD', 'studio0_graphicsIdent_persistent'), + /** + * 1.7.6 + * - Map designs from GFXTemplates to GfxDesignTemplates and delete them from GFXTemplates + */ + mapGfxTemplateToDesignTemplateAndDeleteOriginals('1.7.6', 'QBOX', 'GFXTemplates', 'GfxDesignTemplates'), + + /** + * 1.7.7 + * - Update SourceLayerType for Continuity + * - Update SourceLayerType for DveBackground + */ + forceSourceLayerToDefaults('1.7.7', OfftubeSourceLayer.PgmContinuity), + forceSourceLayerToDefaults('1.7.7', OfftubeSourceLayer.PgmDVEBackground), + ...getSourceLayerDefaultsMigrationSteps(VERSION), ...getOutputLayerDefaultsMigrationSteps(VERSION), GetDefaultAdLibTriggers(VERSION, SHOW_STYLE_ID, {}, GetDefaultStudioSourcesForOfftube, false) diff --git a/src/tv2_offtube_showstyle/migrations/outputlayer-defaults.ts b/src/tv2_offtube_showstyle/migrations/outputlayer-defaults.ts index 3191ee6bc..80aa01067 100644 --- a/src/tv2_offtube_showstyle/migrations/outputlayer-defaults.ts +++ b/src/tv2_offtube_showstyle/migrations/outputlayer-defaults.ts @@ -1,4 +1,4 @@ -import { IOutputLayer } from '@tv2media/blueprints-integration' +import { IOutputLayer } from 'blueprints-integration' import { literal } from 'tv2-common' import { SharedOutputLayers } from 'tv2-constants' diff --git a/src/tv2_offtube_showstyle/migrations/sourcelayer-defaults.ts b/src/tv2_offtube_showstyle/migrations/sourcelayer-defaults.ts index ee3058890..93530a584 100644 --- a/src/tv2_offtube_showstyle/migrations/sourcelayer-defaults.ts +++ b/src/tv2_offtube_showstyle/migrations/sourcelayer-defaults.ts @@ -1,4 +1,4 @@ -import { ISourceLayer, SourceLayerType } from '@tv2media/blueprints-integration' +import { ISourceLayer, SourceLayerType } from 'blueprints-integration' import { GetDSKSourceLayerDefaults, literal } from 'tv2-common' import { SharedSourceLayers } from 'tv2-constants' import { ATEMModel } from '../../types/atem' @@ -279,7 +279,7 @@ const PGM: ISourceLayer[] = [ _rank: 50, name: 'DVE Background', abbreviation: '', - type: SourceLayerType.METADATA, + type: SourceLayerType.UNKNOWN, exclusiveGroup: '', isRemoteInput: false, isGuestInput: false, @@ -294,7 +294,7 @@ const PGM: ISourceLayer[] = [ _rank: 50, name: 'Continuity', abbreviation: 'CONTINUITY', - type: SourceLayerType.METADATA, + type: SourceLayerType.UNKNOWN, exclusiveGroup: '', isRemoteInput: false, isGuestInput: false, @@ -405,6 +405,23 @@ const SEC: ISourceLayer[] = [ isGuestInput: false, isClearable: true, isSticky: false, + isQueueable: false, + isHidden: false, + allowDisable: false, + onPresenterScreen: false + }, + { + _id: SharedSourceLayers.RobotCamera, + _rank: 70, + name: 'Robot Camera', + abbreviation: '', + type: SourceLayerType.UNKNOWN, + exclusiveGroup: '', + isRemoteInput: false, + isGuestInput: false, + + isSticky: false, + isQueueable: false, isHidden: false, allowDisable: false, diff --git a/src/tv2_offtube_showstyle/migrations/util.ts b/src/tv2_offtube_showstyle/migrations/util.ts index 714152f11..5830ed175 100644 --- a/src/tv2_offtube_showstyle/migrations/util.ts +++ b/src/tv2_offtube_showstyle/migrations/util.ts @@ -4,8 +4,8 @@ import { MigrationContextShowStyle, MigrationStepShowStyle, TableConfigItemValue -} from '@tv2media/blueprints-integration' -import { forceSourceLayerToDefaultsBase, literal } from 'tv2-common' +} from 'blueprints-integration' +import { forceSourceLayerToDefaultsBase } from 'tv2-common' import * as _ from 'underscore' import { showStyleConfigManifest } from '../config-manifests' import OutputlayerDefaults from './outputlayer-defaults' @@ -142,41 +142,39 @@ export function remapTableColumnValues( columnId: string, /** Map values [from, to] */ remapping: Map -): MigrationStepShowStyle[] { - return [ - literal({ - id: `${versionStr}.remapTableColumnValue.${tableId}.${columnId}`, - version: versionStr, - canBeRunAutomatically: true, - validate: (context: MigrationContextShowStyle) => { - const table = context.getBaseConfig(tableId) as TableConfigItemValue | undefined - - if (!table || !table.length) { - // No table or no values, nothing to remap - return false - } +): MigrationStepShowStyle { + return { + id: `${versionStr}.remapTableColumnValue.${tableId}.${columnId}`, + version: versionStr, + canBeRunAutomatically: true, + validate: (context: MigrationContextShowStyle) => { + const table = context.getBaseConfig(tableId) as TableConfigItemValue | undefined - const first = table[0] + if (!table || !table.length) { + // No table or no values, nothing to remap + return false + } - if (!Object.keys(first).includes(columnId)) { - return `Column "${columnId}" does not exist in table "${tableId}"` - } + const first = table[0] - const ret = remapTableColumnValuesInner(table, columnId, remapping) + if (!Object.keys(first).includes(columnId)) { + return `Column "${columnId}" does not exist in table "${tableId}"` + } - if (typeof ret === 'string' || typeof ret === 'boolean') { - return ret - } + const ret = remapTableColumnValuesInner(table, columnId, remapping) - return ret.changed !== 0 - }, - migrate: (context: MigrationContextShowStyle) => { - const table = context.getBaseConfig(tableId) as TableConfigItemValue + if (typeof ret === 'string' || typeof ret === 'boolean') { + return ret + } + + return ret.changed !== 0 + }, + migrate: (context: MigrationContextShowStyle) => { + const table = context.getBaseConfig(tableId) as TableConfigItemValue - const ret = remapTableColumnValuesInner(table, columnId, remapping) + const ret = remapTableColumnValuesInner(table, columnId, remapping) - context.setBaseConfig(tableId, ret.table) - } - }) - ] + context.setBaseConfig(tableId, ret.table) + } + } } diff --git a/src/tv2_offtube_showstyle/migrations/variants-defaults.ts b/src/tv2_offtube_showstyle/migrations/variants-defaults.ts index 2767d6458..90827f882 100644 --- a/src/tv2_offtube_showstyle/migrations/variants-defaults.ts +++ b/src/tv2_offtube_showstyle/migrations/variants-defaults.ts @@ -1,4 +1,4 @@ -import { MigrationContextShowStyle, MigrationStepShowStyle } from '@tv2media/blueprints-integration' +import { MigrationContextShowStyle, MigrationStepShowStyle } from 'blueprints-integration' import { literal } from 'tv2-common' import * as _ from 'underscore' diff --git a/src/tv2_offtube_showstyle/onTimelineGenerate.ts b/src/tv2_offtube_showstyle/onTimelineGenerate.ts index 805cbe46f..1650ef7be 100644 --- a/src/tv2_offtube_showstyle/onTimelineGenerate.ts +++ b/src/tv2_offtube_showstyle/onTimelineGenerate.ts @@ -6,7 +6,7 @@ import { PartEndState, TimelinePersistentState, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { disablePilotWipeAfterJingle, onTimelineGenerate, diff --git a/src/tv2_offtube_showstyle/parts/OfftubeDVE.ts b/src/tv2_offtube_showstyle/parts/OfftubeDVE.ts index e4c365924..6975bd53e 100644 --- a/src/tv2_offtube_showstyle/parts/OfftubeDVE.ts +++ b/src/tv2_offtube_showstyle/parts/OfftubeDVE.ts @@ -6,7 +6,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, PartDefinitionDVE, PartTime } from 'tv2-common' import { OfftubeShowstyleBlueprintConfig } from '../helpers/config' import { OfftubeEvaluateCues } from '../helpers/EvaluateCues' diff --git a/src/tv2_offtube_showstyle/parts/OfftubeEffekt.ts b/src/tv2_offtube_showstyle/parts/OfftubeEffekt.ts index b86c22f31..71050555b 100644 --- a/src/tv2_offtube_showstyle/parts/OfftubeEffekt.ts +++ b/src/tv2_offtube_showstyle/parts/OfftubeEffekt.ts @@ -1,4 +1,4 @@ -import { IBlueprintPiece, IShowStyleUserContext } from '@tv2media/blueprints-integration' +import { IBlueprintPiece, IShowStyleUserContext } from 'blueprints-integration' import { CreateEffektForPartBase, PartDefinition } from 'tv2-common' import { SharedSourceLayers } from 'tv2-constants' import { OfftubeCasparLLayer, OfftubeSisyfosLLayer } from '../../tv2_offtube_studio/layers' diff --git a/src/tv2_offtube_showstyle/parts/OfftubeGrafik.ts b/src/tv2_offtube_showstyle/parts/OfftubeGrafik.ts index e04113b16..997ab8a48 100644 --- a/src/tv2_offtube_showstyle/parts/OfftubeGrafik.ts +++ b/src/tv2_offtube_showstyle/parts/OfftubeGrafik.ts @@ -5,7 +5,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, ApplyFullGraphicPropertiesToPart, PartDefinition, PartTime } from 'tv2-common' import { OfftubeShowstyleBlueprintConfig } from '../helpers/config' import { OfftubeEvaluateCues } from '../helpers/EvaluateCues' diff --git a/src/tv2_offtube_showstyle/parts/OfftubeKam.ts b/src/tv2_offtube_showstyle/parts/OfftubeKam.ts index 055679741..4b9ca72fc 100644 --- a/src/tv2_offtube_showstyle/parts/OfftubeKam.ts +++ b/src/tv2_offtube_showstyle/parts/OfftubeKam.ts @@ -10,11 +10,9 @@ import { TSR, VTContent, WithTimeline -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { - AddParentClass, AddScript, - CameraParentClass, CreatePartInvalid, CreatePartKamBase, FindDSKJingle, @@ -51,7 +49,7 @@ export async function OfftubeCreatePartKam( const jingleDSK = FindDSKJingle(config) - if (/cs ?3/i.test(partDefinition.sourceDefinition.id)) { + if (/\bcs *\d*/i.test(partDefinition.sourceDefinition.id)) { pieces.push({ externalId: partDefinition.externalId, name: 'CS 3 (JINGLE)', @@ -127,10 +125,7 @@ export async function OfftubeCreatePartKam( 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) diff --git a/src/tv2_offtube_showstyle/parts/OfftubeServer.ts b/src/tv2_offtube_showstyle/parts/OfftubeServer.ts index 4a72ec850..9252c1fbf 100644 --- a/src/tv2_offtube_showstyle/parts/OfftubeServer.ts +++ b/src/tv2_offtube_showstyle/parts/OfftubeServer.ts @@ -3,7 +3,7 @@ import { HackPartMediaObjectSubscription, IBlueprintActionManifest, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, CreateAdlibServer, CreatePartServerBase, PartDefinition, ServerPartProps } from 'tv2-common' import { OfftubeAtemLLayer, OfftubeCasparLLayer, OfftubeSisyfosLLayer } from '../../tv2_offtube_studio/layers' import { OfftubeShowstyleBlueprintConfig } from '../helpers/config' diff --git a/src/tv2_offtube_showstyle/parts/OfftubeUnknown.ts b/src/tv2_offtube_showstyle/parts/OfftubeUnknown.ts index ececf2cbf..fbdf8535d 100644 --- a/src/tv2_offtube_showstyle/parts/OfftubeUnknown.ts +++ b/src/tv2_offtube_showstyle/parts/OfftubeUnknown.ts @@ -5,7 +5,7 @@ import { IBlueprintPart, IBlueprintPiece, ISegmentUserContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { AddScript, ApplyFullGraphicPropertiesToPart, diff --git a/src/tv2_offtube_showstyle/postProcessTimelineObjects.ts b/src/tv2_offtube_showstyle/postProcessTimelineObjects.ts index 44e44292f..231deb038 100644 --- a/src/tv2_offtube_showstyle/postProcessTimelineObjects.ts +++ b/src/tv2_offtube_showstyle/postProcessTimelineObjects.ts @@ -6,7 +6,7 @@ import { TimelineObjectCoreExt, TimelineObjHoldMode, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { TimelineBlueprintExt, TV2BlueprintConfig } from 'tv2-common' import { ControlClasses } from 'tv2-constants' import _ = require('underscore') diff --git a/src/tv2_offtube_showstyle/syncIngestUpdateToPartInstances.ts b/src/tv2_offtube_showstyle/syncIngestUpdateToPartInstances.ts index 48a42652a..22a06ad6e 100644 --- a/src/tv2_offtube_showstyle/syncIngestUpdateToPartInstances.ts +++ b/src/tv2_offtube_showstyle/syncIngestUpdateToPartInstances.ts @@ -2,7 +2,7 @@ import { BlueprintSyncIngestNewData, BlueprintSyncIngestPartInstance, ISyncIngestUpdateToPartInstanceContext -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { syncIngestUpdateToPartInstanceBase } from 'tv2-common' import { OfftubeSourceLayer } from './layers' diff --git a/src/tv2_offtube_studio/config-manifests.ts b/src/tv2_offtube_studio/config-manifests.ts index 4d70a632c..69eaf00d3 100644 --- a/src/tv2_offtube_studio/config-manifests.ts +++ b/src/tv2_offtube_studio/config-manifests.ts @@ -4,7 +4,7 @@ import { ConfigManifestEntryType, TableConfigItemValue, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { DSKConfigManifest, literal, @@ -285,8 +285,8 @@ export const studioConfigManifest: ConfigManifestEntry[] = [ }, { id: 'HTMLGraphics.GraphicURL', - name: 'Full Graphic URL (HTML)', - description: 'URL to serve full graphics from', + name: 'Pilot Graphic URL (HTML)', + description: 'URL to serve prerendered full/overlay images from', type: ConfigManifestEntryType.STRING, required: false, defaultVal: 'localhost' diff --git a/src/tv2_offtube_studio/getBaseline.ts b/src/tv2_offtube_studio/getBaseline.ts index 7e3ce879d..3b4d9d5c1 100644 --- a/src/tv2_offtube_studio/getBaseline.ts +++ b/src/tv2_offtube_studio/getBaseline.ts @@ -4,7 +4,7 @@ import { BlueprintResultBaseline, IStudioContext, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import { literal } from 'tv2-common' import * as _ from 'underscore' import { AtemSourceIndex } from '../types/atem' diff --git a/src/tv2_offtube_studio/getShowStyleId.ts b/src/tv2_offtube_studio/getShowStyleId.ts index 1c2406d12..d23f72b94 100644 --- a/src/tv2_offtube_studio/getShowStyleId.ts +++ b/src/tv2_offtube_studio/getShowStyleId.ts @@ -1,4 +1,4 @@ -import { IBlueprintShowStyleBase, IngestRundown, IStudioContext } from '@tv2media/blueprints-integration' +import { IBlueprintShowStyleBase, IngestRundown, IStudioContext } from 'blueprints-integration' import * as _ from 'underscore' export function getShowStyleId( diff --git a/src/tv2_offtube_studio/helpers/config.ts b/src/tv2_offtube_studio/helpers/config.ts index 35c497d43..37c23c155 100644 --- a/src/tv2_offtube_studio/helpers/config.ts +++ b/src/tv2_offtube_studio/helpers/config.ts @@ -1,4 +1,4 @@ -import { IBlueprintConfig, ICommonContext } from '@tv2media/blueprints-integration' +import { IBlueprintConfig, ICommonContext } from 'blueprints-integration' import { MediaPlayerConfig, SourceMapping, diff --git a/src/tv2_offtube_studio/helpers/sources.ts b/src/tv2_offtube_studio/helpers/sources.ts index b19c28bd2..4f2875cb5 100644 --- a/src/tv2_offtube_studio/helpers/sources.ts +++ b/src/tv2_offtube_studio/helpers/sources.ts @@ -1,6 +1,6 @@ import * as _ from 'underscore' -import { SourceLayerType } from '@tv2media/blueprints-integration' +import { SourceLayerType } from 'blueprints-integration' import { ParseMappingTable, SourceInfoType, SourceMapping } from 'tv2-common' import { OfftubeStudioConfig } from './config' diff --git a/src/tv2_offtube_studio/index.ts b/src/tv2_offtube_studio/index.ts index 2c5ad9b55..9b2775df0 100644 --- a/src/tv2_offtube_studio/index.ts +++ b/src/tv2_offtube_studio/index.ts @@ -1,4 +1,4 @@ -import { BlueprintManifestType, StudioBlueprintManifest } from '@tv2media/blueprints-integration' +import { BlueprintManifestType, StudioBlueprintManifest } from 'blueprints-integration' import { GetStudioManifestWithMixins, StudioManifestMixinINews } from 'inews-mixins' import * as _ from 'underscore' import { studioConfigManifest } from './config-manifests' diff --git a/src/tv2_offtube_studio/migrations/devices.ts b/src/tv2_offtube_studio/migrations/devices.ts index ae375657d..dbf81e312 100644 --- a/src/tv2_offtube_studio/migrations/devices.ts +++ b/src/tv2_offtube_studio/migrations/devices.ts @@ -4,7 +4,7 @@ import { MigrationStepInputFilteredResult, MigrationStepStudio, TSR -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import * as _ from 'underscore' declare const VERSION: string // Injected by webpack diff --git a/src/tv2_offtube_studio/migrations/index.ts b/src/tv2_offtube_studio/migrations/index.ts index 9c55ff58f..8d9ab9f3a 100644 --- a/src/tv2_offtube_studio/migrations/index.ts +++ b/src/tv2_offtube_studio/migrations/index.ts @@ -1,9 +1,4 @@ -import { - MigrationContextStudio, - MigrationStepStudio, - TableConfigItemValue, - TSR -} from '@tv2media/blueprints-integration' +import { MigrationContextStudio, MigrationStepStudio, TableConfigItemValue, TSR } from 'blueprints-integration' import { AddKeepAudio, MoveClipSourcePath, @@ -306,7 +301,7 @@ export const studioMigrations: MigrationStepStudio[] = [ GetMappingDefaultMigrationStepForLayer('1.5.1', SharedGraphicLLayer.GraphicLLayerAdLibs, true), GetMappingDefaultMigrationStepForLayer('1.5.3', SharedGraphicLLayer.GraphicLLayerWall, true), GetMappingDefaultMigrationStepForLayer('1.5.3', SharedGraphicLLayer.GraphicLLayerPilot, true), - GetMappingDefaultMigrationStepForLayer('1.5.3', SharedGraphicLLayer.GraphicLLayerPilotOverlay, true), + GetMappingDefaultMigrationStepForLayer('1.5.3', SharedGraphicLLayer.GraphicLLayerOverlayPilot, true), GetMappingDefaultMigrationStepForLayer('1.5.3', SharedGraphicLLayer.GraphicLLayerFullLoop, true), SetConfigTo('1.5.3', 'Offtube', 'AtemSource.GFXFull', 12), @@ -362,6 +357,14 @@ export const studioMigrations: MigrationStepStudio[] = [ GetMappingDefaultMigrationStepForLayer('1.7.3', OfftubeCasparLLayer.CasparPlayerJinglePreload, true), GetMappingDefaultMigrationStepForLayer('1.7.3', OfftubeCasparLLayer.CasparPlayerJingle, true), + /** + * 1.7.8 + * - Rename the GraphicLLayerOverlayPilot, because alphabetical order matters for deeply extending the Caspar Objects targeting the same channel:layer + * - Change lookahead properties and channel on GraphicLLayerOverlayPilot + */ + renameMapping('1.7.8', 'graphic_pilot_overlay', 'graphic_overlay_pilot'), + GetMappingDefaultMigrationStepForLayer('1.7.8', 'graphic_overlay_pilot', true), + // Fill in any mappings 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 ...getMappingsDefaultsMigrationSteps(VERSION) diff --git a/src/tv2_offtube_studio/migrations/mappings-defaults.ts b/src/tv2_offtube_studio/migrations/mappings-defaults.ts index d9f85ea41..d7fadb619 100644 --- a/src/tv2_offtube_studio/migrations/mappings-defaults.ts +++ b/src/tv2_offtube_studio/migrations/mappings-defaults.ts @@ -1,4 +1,4 @@ -import { BlueprintMapping, BlueprintMappings, LookaheadMode, TSR } from '@tv2media/blueprints-integration' +import { BlueprintMapping, BlueprintMappings, LookaheadMode, TSR } from 'blueprints-integration' import { AbstractLLayerServerEnable, CasparPlayerClip, @@ -419,18 +419,17 @@ const MAPPINGS_GRAPHICS: BlueprintMappings = { deviceId: 'caspar01', layerName: 'GFX Pilot (Full)', lookahead: LookaheadMode.WHEN_CLEAR, + previewWhenNotOnAir: true, channel: 6, - layer: 108, - previewWhenNotOnAir: true + layer: 108 }), - /** TODO: Revisit these */ - [OfftubeGraphicLLayer.GraphicLLayerPilotOverlay]: literal({ + [OfftubeGraphicLLayer.GraphicLLayerOverlayPilot]: literal({ device: TSR.DeviceType.CASPARCG, deviceId: 'caspar01', layerName: 'GFX Pilot (Overlay)', - lookahead: LookaheadMode.PRELOAD, - previewWhenNotOnAir: true, - channel: 6, + lookahead: LookaheadMode.NONE, + previewWhenNotOnAir: false, + channel: 3, layer: 111 }), // Full loop and DVE loop are the same channel in Q2. diff --git a/src/tv2_offtube_studio/migrations/util.ts b/src/tv2_offtube_studio/migrations/util.ts index 5abc96813..4444c91c7 100644 --- a/src/tv2_offtube_studio/migrations/util.ts +++ b/src/tv2_offtube_studio/migrations/util.ts @@ -5,7 +5,7 @@ import { MigrationStepInput, MigrationStepInputFilteredResult, MigrationStepStudio -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' import * as _ from 'underscore' import { OfftubeSisyfosLLayer } from '../layers' import MappingsDefaults from './mappings-defaults' diff --git a/src/tv2_system/index.ts b/src/tv2_system/index.ts index 9072d563f..1349a8060 100644 --- a/src/tv2_system/index.ts +++ b/src/tv2_system/index.ts @@ -1,4 +1,4 @@ -import { BlueprintManifestType, SystemBlueprintManifest } from '@tv2media/blueprints-integration' +import { BlueprintManifestType, SystemBlueprintManifest } from 'blueprints-integration' import * as _ from 'underscore' import { systemMigrations } from './migrations' diff --git a/src/tv2_system/migrations/hotkeys.ts b/src/tv2_system/migrations/hotkeys.ts index 7f0ce7b08..787f44165 100644 --- a/src/tv2_system/migrations/hotkeys.ts +++ b/src/tv2_system/migrations/hotkeys.ts @@ -5,7 +5,7 @@ import { MigrationStepSystem, PlayoutActions, TriggerType -} from '@tv2media/blueprints-integration' +} from 'blueprints-integration' export function RemoveDefaultCoreShortcuts(versionStr: string): MigrationStepSystem { const defaultTriggerIds = DEFAULT_CORE_TRIGGERS.map(trigger => trigger._id) diff --git a/src/tv2_system/migrations/index.ts b/src/tv2_system/migrations/index.ts index 5d86532c1..f81b2982c 100644 --- a/src/tv2_system/migrations/index.ts +++ b/src/tv2_system/migrations/index.ts @@ -1,4 +1,4 @@ -import { MigrationStepSystem } from '@tv2media/blueprints-integration' +import { MigrationStepSystem } from 'blueprints-integration' import { RemoveDefaultCoreShortcuts } from './hotkeys' declare const VERSION: string // Injected by webpack diff --git a/src/types/blueprints-integration/index.ts b/src/types/blueprints-integration/index.ts new file mode 100644 index 000000000..e22dee460 --- /dev/null +++ b/src/types/blueprints-integration/index.ts @@ -0,0 +1 @@ +export * from '@sofie-automation/blueprints-integration' diff --git a/tsconfig.json b/tsconfig.json index c9f978d99..23e7ae0c6 100755 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,6 +17,9 @@ ], "inews-mixins": [ "src/inews-mixins/index.ts" + ], + "blueprints-integration": [ + "src/types/blueprints-integration/index.ts" ] }, "experimentalDecorators": true diff --git a/tslint.json b/tslint.json index cd0ab88fc..627f97d04 100755 --- a/tslint.json +++ b/tslint.json @@ -7,6 +7,6 @@ "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "require-const-for-all-caps"], "no-bitwise": false, "no-console": false, - "no-implicit-dependencies": [true, ["tv2-common", "tv2-constants", "inews-mixins"]] + "no-implicit-dependencies": [true, ["tv2-common", "tv2-constants", "inews-mixins", "blueprints-integration"]] } } diff --git a/yarn.lock b/yarn.lock index 573b38d9e..56af77daa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -560,21 +560,29 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@sofie-automation/blueprints-integration@npm:@tv2media/blueprints-integration@46.1.0": + version "46.1.0" + resolved "https://registry.yarnpkg.com/@tv2media/blueprints-integration/-/blueprints-integration-46.1.0.tgz#9b2b6f776ecdcd1d0009853bc300452a771a36d5" + integrity sha512-y02lVzd0rNpxyRVUF3FJcnW0uF56Zjc2rsKugZzimd7+XjWSZfFx0Ic35n1Vm2S1+rvb4oSVEh9pvPbpWrCiFg== + dependencies: + "@sofie-automation/shared-lib" "npm:@tv2media/shared-lib@46.1.0" + timeline-state-resolver-types "npm:@tv2media/timeline-state-resolver-types@2.3.1" + tslib "^2.4.0" + type-fest "^2.19.0" + +"@sofie-automation/shared-lib@npm:@tv2media/shared-lib@46.1.0": + version "46.1.0" + resolved "https://registry.yarnpkg.com/@tv2media/shared-lib/-/shared-lib-46.1.0.tgz#ea13b33b0be2feb5cc3d821a6fe992c865f73c5f" + integrity sha512-87h3/w/9vuP6fafH3If8S5j6PlLDSwZGJ1vghpXHHSMtqMV5pm5KZPuT80hGITxXO5GNF1JizaX52Lvb3L6iWw== + dependencies: + tslib "^2.4.0" + type-fest "^2.19.0" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== -"@tv2media/blueprints-integration@1.42.7": - version "1.42.7" - resolved "https://registry.yarnpkg.com/@tv2media/blueprints-integration/-/blueprints-integration-1.42.7.tgz#b88bc4becb27d0b5e828562286bd01cbbb1ee422" - integrity sha512-GAalonu3u6v4bjkM+v0IFDBdKksfMsch7GpsR7Yef7HMpFhEqQvl2rXqd9j3NyQhJKKmywG9Oh081HsvHCfOKg== - dependencies: - moment "2.29.3" - timeline-state-resolver-types "npm:@tv2media/timeline-state-resolver-types@2.1.3" - tslib "^2.3.1" - type-fest "^2.11.1" - "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": version "7.1.19" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" @@ -4413,7 +4421,7 @@ modify-values@^1.0.0: resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== -moment@2.29.3, moment@^2.29.2: +moment@^2.29.2: version "2.29.4" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== @@ -5948,10 +5956,10 @@ through@2, "through@>=2.2.7 <3": resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -"timeline-state-resolver-types@npm:@tv2media/timeline-state-resolver-types@2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@tv2media/timeline-state-resolver-types/-/timeline-state-resolver-types-2.1.3.tgz#b79f4a5449428c517398bc908e93c13477ff04a8" - integrity sha512-wHW2S/Q/i2Dn7QPjY8nCdfjGG/a8BCvMfuI/vMm9WTqfzRnBgh9S8gd4TmOFUEaAiEZNGRy/wR6Y0ZquLYQ0mQ== +"timeline-state-resolver-types@npm:@tv2media/timeline-state-resolver-types@2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@tv2media/timeline-state-resolver-types/-/timeline-state-resolver-types-2.3.1.tgz#8c29069c84ea086d9eb9e48e5f2f244cc5f1e823" + integrity sha512-T78ObNn8pd4we4fCdX4VcUDeSRV+X0L//tdmLFEaHqrAMY3TBAS36oTsLHvU+az5m1wqns7EBXFbu9FystVQFQ== dependencies: tslib "^2.3.1" @@ -6100,6 +6108,11 @@ tslib@^2.3.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== +tslib@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tslint-config-prettier@^1.18.0: version "1.18.0" resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz#75f140bde947d35d8f0d238e0ebf809d64592c37" @@ -6177,10 +6190,10 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-fest@^2.11.1: - version "2.12.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.2.tgz#80a53614e6b9b475eb9077472fb7498dc7aa51d0" - integrity sha512-qt6ylCGpLjZ7AaODxbpyBZSs9fCI9SkL3Z9q2oxMBQhs/uyY+VD8jHA8ULCGmWQJlBgqvO3EJeAngOHD8zQCrQ== +type-fest@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== typedarray-to-buffer@^3.1.5: version "3.1.5"