From bd1f66c3305a80098c6953e1d0332ff5994680b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 06:25:59 +0000 Subject: [PATCH 01/30] chore(deps): bump aquasecurity/trivy-action from 0.24.0 to 0.27.0 Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.24.0 to 0.27.0. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.24.0...0.27.0) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/node.yaml | 4 ++-- .github/workflows/trivy.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/node.yaml b/.github/workflows/node.yaml index fb50334747..b42d56d19d 100644 --- a/.github/workflows/node.yaml +++ b/.github/workflows/node.yaml @@ -239,7 +239,7 @@ jobs: echo "image=$image" >> $GITHUB_OUTPUT - name: Trivy scanning if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true' && steps.ghcr-tag.outputs.tags != 0 - uses: aquasecurity/trivy-action@0.24.0 + uses: aquasecurity/trivy-action@0.27.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: @@ -390,7 +390,7 @@ jobs: echo "image=$image" >> $GITHUB_OUTPUT - name: Trivy scanning if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true' && steps.ghcr-tag.outputs.tags != 0 - uses: aquasecurity/trivy-action@0.24.0 + uses: aquasecurity/trivy-action@0.27.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 212a538f80..d672633857 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Run Trivy vulnerability scanner (json) - uses: aquasecurity/trivy-action@0.24.0 + uses: aquasecurity/trivy-action@0.27.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: @@ -26,7 +26,7 @@ jobs: output: '${{ matrix.image }}-trivy-scan-results.json' - name: Run Trivy vulnerability scanner (table) - uses: aquasecurity/trivy-action@0.24.0 + uses: aquasecurity/trivy-action@0.27.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: @@ -44,7 +44,7 @@ jobs: echo $CODE_BLOCK >> $GITHUB_STEP_SUMMARY - name: Run Trivy in GitHub SBOM mode and submit results to Dependency Graph - uses: aquasecurity/trivy-action@0.24.0 + uses: aquasecurity/trivy-action@0.27.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: From 9a8ffbf0bd5837afc054dd7d74ced715d3f815e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 06:41:09 +0000 Subject: [PATCH 02/30] chore(deps): bump aquasecurity/trivy-action from 0.27.0 to 0.28.0 Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.27.0 to 0.28.0. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.27.0...0.28.0) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/node.yaml | 4 ++-- .github/workflows/trivy.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/node.yaml b/.github/workflows/node.yaml index b42d56d19d..8811dc442d 100644 --- a/.github/workflows/node.yaml +++ b/.github/workflows/node.yaml @@ -239,7 +239,7 @@ jobs: echo "image=$image" >> $GITHUB_OUTPUT - name: Trivy scanning if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true' && steps.ghcr-tag.outputs.tags != 0 - uses: aquasecurity/trivy-action@0.27.0 + uses: aquasecurity/trivy-action@0.28.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: @@ -390,7 +390,7 @@ jobs: echo "image=$image" >> $GITHUB_OUTPUT - name: Trivy scanning if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true' && steps.ghcr-tag.outputs.tags != 0 - uses: aquasecurity/trivy-action@0.27.0 + uses: aquasecurity/trivy-action@0.28.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index d672633857..1b361d1978 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Run Trivy vulnerability scanner (json) - uses: aquasecurity/trivy-action@0.27.0 + uses: aquasecurity/trivy-action@0.28.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: @@ -26,7 +26,7 @@ jobs: output: '${{ matrix.image }}-trivy-scan-results.json' - name: Run Trivy vulnerability scanner (table) - uses: aquasecurity/trivy-action@0.27.0 + uses: aquasecurity/trivy-action@0.28.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: @@ -44,7 +44,7 @@ jobs: echo $CODE_BLOCK >> $GITHUB_STEP_SUMMARY - name: Run Trivy in GitHub SBOM mode and submit results to Dependency Graph - uses: aquasecurity/trivy-action@0.27.0 + uses: aquasecurity/trivy-action@0.28.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: From 874e85ccbf6d9438c17d550c98ebb8e81df44e48 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Mon, 4 Nov 2024 11:12:32 +0100 Subject: [PATCH 03/30] fix: RundownView shows spinner when unMOSing a Rundown from a Playlist --- .../lib/ReactMeteorData/ReactMeteorData.tsx | 121 ++++++++++++++++-- meteor/client/ui/RundownView.tsx | 15 ++- 2 files changed, 123 insertions(+), 13 deletions(-) diff --git a/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx b/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx index df3ddd7d30..efe17b7371 100644 --- a/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx +++ b/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx @@ -1,6 +1,6 @@ /* eslint-disable react/prefer-stateless-function */ -import React, { useState, useEffect, useRef } from 'react' +import React, { useState, useEffect, useRef, useCallback } from 'react' import { Meteor } from 'meteor/meteor' import { Mongo } from 'meteor/mongo' import { Tracker } from 'meteor/tracker' @@ -13,6 +13,8 @@ const globalTrackerQueue: Array = [] let globalTrackerTimestamp: number | undefined = undefined let globalTrackerTimeout: number | undefined = undefined +const SUBSCRIPTION_TIMEOUT = 1000 + /** * Delay an update to be batched with the global tracker invalidation queue */ @@ -370,6 +372,46 @@ export function useTracker( return meteorData } +function useReadyState(): { + ready: boolean + setReady: (value: boolean) => void + cancelPreviousReady: (timeout: number) => void +} { + const [ready, setReady] = useState(false) + const [prevReady, setPrevReady] = useState(false) + const prevReadyTimeoutRef = useRef(null) + + const setIsReady = useCallback( + (value: boolean) => { + setReady(value) + + if (value) { + setPrevReady(true) + if (prevReadyTimeoutRef.current !== null) { + window.clearTimeout(prevReadyTimeoutRef.current) + prevReadyTimeoutRef.current = null + } + } + }, + [setReady, setPrevReady] + ) + + const cancelPrevReady = useCallback( + (timeout: number) => { + prevReadyTimeoutRef.current = window.setTimeout(() => { + setPrevReady(false) + }, timeout) + }, + [prevReadyTimeoutRef] + ) + + return { + ready: ready || prevReady, + setReady: setIsReady, + cancelPreviousReady: cancelPrevReady, + } +} + /** * A Meteor Subscription hook that allows using React Functional Components and the Hooks API with Meteor subscriptions. * Subscriptions will be torn down 1000ms after unmounting the component. @@ -383,20 +425,28 @@ export function useSubscription( sub: K, ...args: Parameters ): boolean { - const [ready, setReady] = useState(false) + const { ready, setReady, cancelPreviousReady } = useReadyState() useEffect(() => { const subscription = Tracker.nonreactive(() => meteorSubscribe(sub, ...args)) - const isReadyComp = Tracker.nonreactive(() => Tracker.autorun(() => setReady(subscription.ready()))) + const isReadyComp = Tracker.nonreactive(() => + Tracker.autorun(() => { + const isNowReady = subscription.ready() + setReady(isNowReady) + }) + ) return () => { isReadyComp.stop() setTimeout(() => { subscription.stop() - }, 1000) + }, SUBSCRIPTION_TIMEOUT) + cancelPreviousReady(SUBSCRIPTION_TIMEOUT) } }, [sub, stringifyObjects(args)]) - return ready + const isReady = ready + + return isReady } /** @@ -415,7 +465,7 @@ export function useSubscriptionIfEnabled( enable: boolean, ...args: Parameters ): boolean { - const [ready, setReady] = useState(false) + const { ready, setReady, cancelPreviousReady } = useReadyState() useEffect(() => { if (!enable) { @@ -424,16 +474,69 @@ export function useSubscriptionIfEnabled( } const subscription = Tracker.nonreactive(() => meteorSubscribe(sub, ...args)) - const isReadyComp = Tracker.nonreactive(() => Tracker.autorun(() => setReady(subscription.ready()))) + const isReadyComp = Tracker.nonreactive(() => + Tracker.autorun(() => { + const isNowReady = subscription.ready() + setReady(isNowReady) + }) + ) return () => { isReadyComp.stop() setTimeout(() => { subscription.stop() - }, 1000) + }, SUBSCRIPTION_TIMEOUT) + cancelPreviousReady(SUBSCRIPTION_TIMEOUT) } }, [sub, enable, stringifyObjects(args)]) - return !enable || ready + const isReady = !enable || ready + + return isReady +} + +/** + * A Meteor Subscription hook that allows using React Functional Components and the Hooks API with Meteor subscriptions. + * Subscriptions will be torn down 1000ms after unmounting the component. + * If the subscription is not enabled, the subscription will not be created, and the ready state will always be true. + * + * @export + * @param {PubSub} sub The subscription to be subscribed to + * @param {boolean} enable Whether the subscription is enabled + * @param {...any[]} args A list of arugments for the subscription. This is used for optimizing the subscription across + * renders so that it isn't torn down and created for every render. + */ +export function useSubscriptionIfEnabledReadyOnce( + sub: K, + enable: boolean, + ...args: Parameters +): boolean { + const { ready, setReady, cancelPreviousReady } = useReadyState() + + useEffect(() => { + if (!enable) { + setReady(false) + return + } + + const subscription = Tracker.nonreactive(() => meteorSubscribe(sub, ...args)) + const isReadyComp = Tracker.nonreactive(() => + Tracker.autorun(() => { + const isNowReady = subscription.ready() + if (isNowReady) setReady(true) + }) + ) + return () => { + isReadyComp.stop() + setTimeout(() => { + subscription.stop() + }, SUBSCRIPTION_TIMEOUT) + cancelPreviousReady(SUBSCRIPTION_TIMEOUT) + } + }, [sub, enable, stringifyObjects(args)]) + + const isReady = !enable || ready + + return isReady } /** diff --git a/meteor/client/ui/RundownView.tsx b/meteor/client/ui/RundownView.tsx index a6ce8517e3..6b949b0c69 100644 --- a/meteor/client/ui/RundownView.tsx +++ b/meteor/client/ui/RundownView.tsx @@ -7,6 +7,7 @@ import { Translated, translateWithTracker, useSubscriptionIfEnabled, + useSubscriptionIfEnabledReadyOnce, useSubscriptions, useTracker, } from '../lib/ReactMeteorData/react-meteor-data' @@ -1227,9 +1228,6 @@ export function RundownView(props: Readonly): JSX.Element { return playlist?.studioId }, [playlistId]) - // Load once the playlist is confirmed to exist - auxSubsReady.push(useSubscriptionIfEnabled(MeteorPubSub.uiSegmentPartNotes, !!playlistStudioId, playlistId)) - auxSubsReady.push(useSubscriptionIfEnabled(MeteorPubSub.uiPieceContentStatuses, !!playlistStudioId, playlistId)) // Load only when the studio is known requiredSubsReady.push( useSubscriptionIfEnabled(MeteorPubSub.uiStudio, !!playlistStudioId, playlistStudioId ?? protectString('')) @@ -1258,7 +1256,12 @@ export function RundownView(props: Readonly): JSX.Element { ) ) requiredSubsReady.push( - useSubscriptionIfEnabled(CorelibPubSub.showStyleVariants, showStyleVariantIds.length > 0, null, showStyleVariantIds) + useSubscriptionIfEnabledReadyOnce( + CorelibPubSub.showStyleVariants, + showStyleVariantIds.length > 0, + null, + showStyleVariantIds + ) ) auxSubsReady.push( useSubscriptionIfEnabled(MeteorPubSub.rundownLayouts, showStyleBaseIds.length > 0, showStyleBaseIds) @@ -1283,6 +1286,10 @@ export function RundownView(props: Readonly): JSX.Element { ) ) + // Load once the playlist is confirmed to exist + auxSubsReady.push(useSubscriptionIfEnabled(MeteorPubSub.uiSegmentPartNotes, !!playlistStudioId, playlistId)) + auxSubsReady.push(useSubscriptionIfEnabled(MeteorPubSub.uiPieceContentStatuses, !!playlistStudioId, playlistId)) + useTracker(() => { const playlist = RundownPlaylists.findOne(playlistId, { fields: { From 7ba4904c1de685c834e1875f4c84f0f514afe643 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Wed, 13 Nov 2024 12:20:46 +0100 Subject: [PATCH 04/30] chore: update deps --- meteor/yarn.lock | 10 +++++----- packages/playout-gateway/package.json | 2 +- packages/shared-lib/package.json | 2 +- packages/yarn.lock | 22 +++++++++++----------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/meteor/yarn.lock b/meteor/yarn.lock index 14f493ab69..ecd663ed71 100644 --- a/meteor/yarn.lock +++ b/meteor/yarn.lock @@ -1418,7 +1418,7 @@ __metadata: resolution: "@sofie-automation/shared-lib@portal:../packages/shared-lib::locator=automation-core%40workspace%3A." dependencies: "@mos-connection/model": ^4.1.1 - timeline-state-resolver-types: 9.2.1-nightly-release51-20241010-074534-2b45bc89d.0 + timeline-state-resolver-types: 9.2.0 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: node @@ -11748,12 +11748,12 @@ __metadata: languageName: node linkType: hard -"timeline-state-resolver-types@npm:9.2.1-nightly-release51-20241010-074534-2b45bc89d.0": - version: 9.2.1-nightly-release51-20241010-074534-2b45bc89d.0 - resolution: "timeline-state-resolver-types@npm:9.2.1-nightly-release51-20241010-074534-2b45bc89d.0" +"timeline-state-resolver-types@npm:9.2.0": + version: 9.2.0 + resolution: "timeline-state-resolver-types@npm:9.2.0" dependencies: tslib: ^2.6.2 - checksum: 6d771f06049be7f75bd1f62c904b2ebfe4050c3e9e2522e73f0cbfadb7cb20ed60a179ed85b7624b0f2bf766dab0fb278b693231d211001b9bc5d3686c35a942 + checksum: aa51cff0d18b16c613705583f5a1c087e44df59b4b5a7e0fe2f31e52f492686a326bb3a63493b828b166dc8196d58d1470e2adcb730439e8c9ef522e796aea4e languageName: node linkType: hard diff --git a/packages/playout-gateway/package.json b/packages/playout-gateway/package.json index f48018a67e..f2f539cd66 100644 --- a/packages/playout-gateway/package.json +++ b/packages/playout-gateway/package.json @@ -60,7 +60,7 @@ "@sofie-automation/shared-lib": "1.51.1-2", "debug": "^4.3.4", "influx": "^5.9.3", - "timeline-state-resolver": "9.2.1-nightly-release51-20241010-074534-2b45bc89d.0", + "timeline-state-resolver": "9.2.1", "tslib": "^2.6.2", "underscore": "^1.13.6", "winston": "^3.11.0" diff --git a/packages/shared-lib/package.json b/packages/shared-lib/package.json index 5955c6c9cc..fe61cfa8f3 100644 --- a/packages/shared-lib/package.json +++ b/packages/shared-lib/package.json @@ -39,7 +39,7 @@ ], "dependencies": { "@mos-connection/model": "^4.1.1", - "timeline-state-resolver-types": "9.2.1-nightly-release51-20241010-074534-2b45bc89d.0", + "timeline-state-resolver-types": "9.2.0", "tslib": "^2.6.2", "type-fest": "^3.13.1" }, diff --git a/packages/yarn.lock b/packages/yarn.lock index a826ab9b99..94f2bf92e8 100644 --- a/packages/yarn.lock +++ b/packages/yarn.lock @@ -4693,7 +4693,7 @@ __metadata: resolution: "@sofie-automation/shared-lib@workspace:shared-lib" dependencies: "@mos-connection/model": ^4.1.1 - timeline-state-resolver-types: 9.2.1-nightly-release51-20241010-074534-2b45bc89d.0 + timeline-state-resolver-types: 9.2.0 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: unknown @@ -19401,7 +19401,7 @@ asn1@evs-broadcast/node-asn1: "@sofie-automation/shared-lib": 1.51.1-2 debug: ^4.3.4 influx: ^5.9.3 - timeline-state-resolver: 9.2.1-nightly-release51-20241010-074534-2b45bc89d.0 + timeline-state-resolver: 9.2.1 tslib: ^2.6.2 underscore: ^1.13.6 winston: ^3.11.0 @@ -22997,18 +22997,18 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"timeline-state-resolver-types@npm:9.2.1-nightly-release51-20241010-074534-2b45bc89d.0": - version: 9.2.1-nightly-release51-20241010-074534-2b45bc89d.0 - resolution: "timeline-state-resolver-types@npm:9.2.1-nightly-release51-20241010-074534-2b45bc89d.0" +"timeline-state-resolver-types@npm:9.2.0": + version: 9.2.0 + resolution: "timeline-state-resolver-types@npm:9.2.0" dependencies: tslib: ^2.6.2 - checksum: 6d771f06049be7f75bd1f62c904b2ebfe4050c3e9e2522e73f0cbfadb7cb20ed60a179ed85b7624b0f2bf766dab0fb278b693231d211001b9bc5d3686c35a942 + checksum: aa51cff0d18b16c613705583f5a1c087e44df59b4b5a7e0fe2f31e52f492686a326bb3a63493b828b166dc8196d58d1470e2adcb730439e8c9ef522e796aea4e languageName: node linkType: hard -"timeline-state-resolver@npm:9.2.1-nightly-release51-20241010-074534-2b45bc89d.0": - version: 9.2.1-nightly-release51-20241010-074534-2b45bc89d.0 - resolution: "timeline-state-resolver@npm:9.2.1-nightly-release51-20241010-074534-2b45bc89d.0" +"timeline-state-resolver@npm:9.2.1": + version: 9.2.1 + resolution: "timeline-state-resolver@npm:9.2.1" dependencies: "@tv2media/v-connection": ^7.3.2 atem-connection: 3.5.0 @@ -23033,7 +23033,7 @@ asn1@evs-broadcast/node-asn1: sprintf-js: ^1.1.3 superfly-timeline: 9.0.2 threadedclass: ^1.2.1 - timeline-state-resolver-types: 9.2.1-nightly-release51-20241010-074534-2b45bc89d.0 + timeline-state-resolver-types: 9.2.0 tslib: ^2.6.2 tv-automation-quantel-gateway-client: ^3.1.7 type-fest: ^3.13.1 @@ -23041,7 +23041,7 @@ asn1@evs-broadcast/node-asn1: utf-8-validate: ^5.0.10 ws: ^7.5.10 xml-js: ^1.6.11 - checksum: b66346bb52e124486b91593340c2b58968c07e27b9e00857a47d37f7e59a24703e2283561231fb18fa12c3d5ddbb269fff2d3f162225fb5d083208973c96ab87 + checksum: 63e8989b11e39eb66acde4bc872ba8ec4444971c3152bd39f08a3f9622a379716258a0eeae65346622ef9f644cebca76415c4d74cd4a98d8d387f0783161c49e languageName: node linkType: hard From d908ac61a935e3b8a5764750556e40bcaa1af344 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Wed, 13 Nov 2024 13:08:20 +0100 Subject: [PATCH 05/30] chore(release): 1.51.1 --- meteor/package.json | 2 +- meteor/yarn.lock | 12 +++--- packages/blueprints-integration/CHANGELOG.md | 8 ++++ packages/blueprints-integration/package.json | 4 +- packages/corelib/package.json | 6 +-- packages/documentation/package.json | 2 +- packages/job-worker/package.json | 8 ++-- packages/lerna.json | 2 +- packages/live-status-gateway/package.json | 10 ++--- packages/mos-gateway/CHANGELOG.md | 8 ++++ packages/mos-gateway/package.json | 6 +-- packages/openapi/package.json | 2 +- packages/playout-gateway/CHANGELOG.md | 8 ++++ packages/playout-gateway/package.json | 6 +-- packages/server-core-integration/CHANGELOG.md | 8 ++++ packages/server-core-integration/package.json | 4 +- packages/shared-lib/package.json | 2 +- packages/yarn.lock | 38 +++++++++---------- 18 files changed, 84 insertions(+), 52 deletions(-) diff --git a/meteor/package.json b/meteor/package.json index c7a96a7959..ecffd16981 100644 --- a/meteor/package.json +++ b/meteor/package.json @@ -1,6 +1,6 @@ { "name": "automation-core", - "version": "1.51.1-2", + "version": "1.51.1", "private": true, "engines": { "node": ">=14.19.1" diff --git a/meteor/yarn.lock b/meteor/yarn.lock index ecd663ed71..d3495e4ec4 100644 --- a/meteor/yarn.lock +++ b/meteor/yarn.lock @@ -1321,7 +1321,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@portal:../packages/blueprints-integration::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/shared-lib": 1.51.1-2 + "@sofie-automation/shared-lib": 1.51.1 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: node @@ -1362,8 +1362,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/corelib@portal:../packages/corelib::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/blueprints-integration": 1.51.1-2 - "@sofie-automation/shared-lib": 1.51.1-2 + "@sofie-automation/blueprints-integration": 1.51.1 + "@sofie-automation/shared-lib": 1.51.1 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -1394,9 +1394,9 @@ __metadata: resolution: "@sofie-automation/job-worker@portal:../packages/job-worker::locator=automation-core%40workspace%3A." dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.1-2 - "@sofie-automation/corelib": 1.51.1-2 - "@sofie-automation/shared-lib": 1.51.1-2 + "@sofie-automation/blueprints-integration": 1.51.1 + "@sofie-automation/corelib": 1.51.1 + "@sofie-automation/shared-lib": 1.51.1 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 diff --git a/packages/blueprints-integration/CHANGELOG.md b/packages/blueprints-integration/CHANGELOG.md index 1c3adfcbfe..2c8414a48b 100644 --- a/packages/blueprints-integration/CHANGELOG.md +++ b/packages/blueprints-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.1](https://github.com/nrkno/sofie-core/compare/v1.51.1-2...v1.51.1) (2024-11-13) + +**Note:** Version bump only for package @sofie-automation/blueprints-integration + + + + + ## [1.51.1-2](https://github.com/nrkno/sofie-core/compare/v1.51.1-1...v1.51.1-2) (2024-10-24) **Note:** Version bump only for package @sofie-automation/blueprints-integration diff --git a/packages/blueprints-integration/package.json b/packages/blueprints-integration/package.json index 3236ce8c9f..f29f8e3d83 100644 --- a/packages/blueprints-integration/package.json +++ b/packages/blueprints-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/blueprints-integration", - "version": "1.51.1-2", + "version": "1.51.1", "description": "Library to define the interaction between core and the blueprints.", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -38,7 +38,7 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.1-2", + "@sofie-automation/shared-lib": "1.51.1", "tslib": "^2.6.2", "type-fest": "^3.13.1" }, diff --git a/packages/corelib/package.json b/packages/corelib/package.json index a8632c5024..49d556e657 100644 --- a/packages/corelib/package.json +++ b/packages/corelib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/corelib", - "version": "1.51.1-2", + "version": "1.51.1", "private": true, "description": "Internal library for some types shared by core and workers", "main": "dist/index.js", @@ -39,8 +39,8 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.1-2", - "@sofie-automation/shared-lib": "1.51.1-2", + "@sofie-automation/blueprints-integration": "1.51.1", + "@sofie-automation/shared-lib": "1.51.1", "fast-clone": "^1.5.13", "i18next": "^21.10.0", "influx": "^5.9.3", diff --git a/packages/documentation/package.json b/packages/documentation/package.json index 488a4d6ced..9e5367c3a7 100644 --- a/packages/documentation/package.json +++ b/packages/documentation/package.json @@ -1,6 +1,6 @@ { "name": "sofie-documentation", - "version": "1.51.1-2", + "version": "1.51.1", "private": true, "scripts": { "docusaurus": "docusaurus", diff --git a/packages/job-worker/package.json b/packages/job-worker/package.json index de48ac7717..c15e1e6ffd 100644 --- a/packages/job-worker/package.json +++ b/packages/job-worker/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/job-worker", - "version": "1.51.1-2", + "version": "1.51.1", "description": "Worker for things", "main": "dist/index.js", "license": "MIT", @@ -41,9 +41,9 @@ ], "dependencies": { "@slack/webhook": "^6.1.0", - "@sofie-automation/blueprints-integration": "1.51.1-2", - "@sofie-automation/corelib": "1.51.1-2", - "@sofie-automation/shared-lib": "1.51.1-2", + "@sofie-automation/blueprints-integration": "1.51.1", + "@sofie-automation/corelib": "1.51.1", + "@sofie-automation/shared-lib": "1.51.1", "amqplib": "^0.10.3", "deepmerge": "^4.3.1", "elastic-apm-node": "^3.51.0", diff --git a/packages/lerna.json b/packages/lerna.json index 002bf98d8a..d3ac537e86 100644 --- a/packages/lerna.json +++ b/packages/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.51.1-2", + "version": "1.51.1", "npmClient": "yarn", "useWorkspaces": true } diff --git a/packages/live-status-gateway/package.json b/packages/live-status-gateway/package.json index f6400973a0..6ffc183cba 100644 --- a/packages/live-status-gateway/package.json +++ b/packages/live-status-gateway/package.json @@ -1,6 +1,6 @@ { "name": "live-status-gateway", - "version": "1.51.1-2", + "version": "1.51.1", "private": true, "description": "Provides state from Sofie over sockets", "license": "MIT", @@ -53,10 +53,10 @@ "production" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.1-2", - "@sofie-automation/corelib": "1.51.1-2", - "@sofie-automation/server-core-integration": "1.51.1-2", - "@sofie-automation/shared-lib": "1.51.1-2", + "@sofie-automation/blueprints-integration": "1.51.1", + "@sofie-automation/corelib": "1.51.1", + "@sofie-automation/server-core-integration": "1.51.1", + "@sofie-automation/shared-lib": "1.51.1", "debug": "^4.3.4", "fast-clone": "^1.5.13", "influx": "^5.9.3", diff --git a/packages/mos-gateway/CHANGELOG.md b/packages/mos-gateway/CHANGELOG.md index 097ebaf45e..c8adfc4ea2 100644 --- a/packages/mos-gateway/CHANGELOG.md +++ b/packages/mos-gateway/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.1](https://github.com/nrkno/sofie-core/compare/v1.51.1-2...v1.51.1) (2024-11-13) + +**Note:** Version bump only for package mos-gateway + + + + + ## [1.51.1-2](https://github.com/nrkno/sofie-core/compare/v1.51.1-1...v1.51.1-2) (2024-10-24) **Note:** Version bump only for package mos-gateway diff --git a/packages/mos-gateway/package.json b/packages/mos-gateway/package.json index 0b144c2c38..6db3bd8572 100644 --- a/packages/mos-gateway/package.json +++ b/packages/mos-gateway/package.json @@ -1,6 +1,6 @@ { "name": "mos-gateway", - "version": "1.51.1-2", + "version": "1.51.1", "private": true, "description": "MOS-Gateway for the Sofie project", "license": "MIT", @@ -66,8 +66,8 @@ ], "dependencies": { "@mos-connection/connector": "4.1.1", - "@sofie-automation/server-core-integration": "1.51.1-2", - "@sofie-automation/shared-lib": "1.51.1-2", + "@sofie-automation/server-core-integration": "1.51.1", + "@sofie-automation/shared-lib": "1.51.1", "tslib": "^2.6.2", "type-fest": "^3.13.1", "underscore": "^1.13.6", diff --git a/packages/openapi/package.json b/packages/openapi/package.json index 187a896bf9..45d4c33902 100644 --- a/packages/openapi/package.json +++ b/packages/openapi/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/openapi", - "version": "1.51.1-2", + "version": "1.51.1", "license": "MIT", "repository": { "type": "git", diff --git a/packages/playout-gateway/CHANGELOG.md b/packages/playout-gateway/CHANGELOG.md index 334fc18216..00c009e113 100644 --- a/packages/playout-gateway/CHANGELOG.md +++ b/packages/playout-gateway/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.1](https://github.com/nrkno/sofie-core/compare/v1.51.1-2...v1.51.1) (2024-11-13) + +**Note:** Version bump only for package playout-gateway + + + + + ## [1.51.1-2](https://github.com/nrkno/sofie-core/compare/v1.51.1-1...v1.51.1-2) (2024-10-24) **Note:** Version bump only for package playout-gateway diff --git a/packages/playout-gateway/package.json b/packages/playout-gateway/package.json index f2f539cd66..327e433748 100644 --- a/packages/playout-gateway/package.json +++ b/packages/playout-gateway/package.json @@ -1,6 +1,6 @@ { "name": "playout-gateway", - "version": "1.51.1-2", + "version": "1.51.1", "private": true, "description": "Connect to Core, play stuff", "license": "MIT", @@ -56,8 +56,8 @@ "production" ], "dependencies": { - "@sofie-automation/server-core-integration": "1.51.1-2", - "@sofie-automation/shared-lib": "1.51.1-2", + "@sofie-automation/server-core-integration": "1.51.1", + "@sofie-automation/shared-lib": "1.51.1", "debug": "^4.3.4", "influx": "^5.9.3", "timeline-state-resolver": "9.2.1", diff --git a/packages/server-core-integration/CHANGELOG.md b/packages/server-core-integration/CHANGELOG.md index 66c7282306..d374832bf1 100644 --- a/packages/server-core-integration/CHANGELOG.md +++ b/packages/server-core-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.1](https://github.com/nrkno/sofie-core/compare/v1.51.1-2...v1.51.1) (2024-11-13) + +**Note:** Version bump only for package @sofie-automation/server-core-integration + + + + + ## [1.51.1-2](https://github.com/nrkno/sofie-core/compare/v1.51.1-1...v1.51.1-2) (2024-10-24) **Note:** Version bump only for package @sofie-automation/server-core-integration diff --git a/packages/server-core-integration/package.json b/packages/server-core-integration/package.json index a179de692d..c8db37a4e0 100644 --- a/packages/server-core-integration/package.json +++ b/packages/server-core-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/server-core-integration", - "version": "1.51.1-2", + "version": "1.51.1", "description": "Library for connecting to Core", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -70,7 +70,7 @@ "production" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.1-2", + "@sofie-automation/shared-lib": "1.51.1", "ejson": "^2.2.3", "eventemitter3": "^4.0.7", "faye-websocket": "^0.11.4", diff --git a/packages/shared-lib/package.json b/packages/shared-lib/package.json index fe61cfa8f3..8047b89da7 100644 --- a/packages/shared-lib/package.json +++ b/packages/shared-lib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/shared-lib", - "version": "1.51.1-2", + "version": "1.51.1", "description": "Library for types & values shared by core, workers and gateways", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/packages/yarn.lock b/packages/yarn.lock index 94f2bf92e8..bf3167a4e3 100644 --- a/packages/yarn.lock +++ b/packages/yarn.lock @@ -4565,11 +4565,11 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/blueprints-integration@1.51.1-2, @sofie-automation/blueprints-integration@workspace:blueprints-integration": +"@sofie-automation/blueprints-integration@1.51.1, @sofie-automation/blueprints-integration@workspace:blueprints-integration": version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@workspace:blueprints-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.1-2 + "@sofie-automation/shared-lib": 1.51.1 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: unknown @@ -4606,12 +4606,12 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/corelib@1.51.1-2, @sofie-automation/corelib@workspace:corelib": +"@sofie-automation/corelib@1.51.1, @sofie-automation/corelib@workspace:corelib": version: 0.0.0-use.local resolution: "@sofie-automation/corelib@workspace:corelib" dependencies: - "@sofie-automation/blueprints-integration": 1.51.1-2 - "@sofie-automation/shared-lib": 1.51.1-2 + "@sofie-automation/blueprints-integration": 1.51.1 + "@sofie-automation/shared-lib": 1.51.1 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -4642,9 +4642,9 @@ __metadata: resolution: "@sofie-automation/job-worker@workspace:job-worker" dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.1-2 - "@sofie-automation/corelib": 1.51.1-2 - "@sofie-automation/shared-lib": 1.51.1-2 + "@sofie-automation/blueprints-integration": 1.51.1 + "@sofie-automation/corelib": 1.51.1 + "@sofie-automation/shared-lib": 1.51.1 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 @@ -4674,11 +4674,11 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/server-core-integration@1.51.1-2, @sofie-automation/server-core-integration@workspace:server-core-integration": +"@sofie-automation/server-core-integration@1.51.1, @sofie-automation/server-core-integration@workspace:server-core-integration": version: 0.0.0-use.local resolution: "@sofie-automation/server-core-integration@workspace:server-core-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.1-2 + "@sofie-automation/shared-lib": 1.51.1 ejson: ^2.2.3 eventemitter3: ^4.0.7 faye-websocket: ^0.11.4 @@ -4688,7 +4688,7 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/shared-lib@1.51.1-2, @sofie-automation/shared-lib@workspace:shared-lib": +"@sofie-automation/shared-lib@1.51.1, @sofie-automation/shared-lib@workspace:shared-lib": version: 0.0.0-use.local resolution: "@sofie-automation/shared-lib@workspace:shared-lib" dependencies: @@ -15334,10 +15334,10 @@ asn1@evs-broadcast/node-asn1: "@asyncapi/generator": ^1.17.25 "@asyncapi/html-template": ^2.3.9 "@asyncapi/nodejs-ws-template": ^0.9.36 - "@sofie-automation/blueprints-integration": 1.51.1-2 - "@sofie-automation/corelib": 1.51.1-2 - "@sofie-automation/server-core-integration": 1.51.1-2 - "@sofie-automation/shared-lib": 1.51.1-2 + "@sofie-automation/blueprints-integration": 1.51.1 + "@sofie-automation/corelib": 1.51.1 + "@sofie-automation/server-core-integration": 1.51.1 + "@sofie-automation/shared-lib": 1.51.1 debug: ^4.3.4 fast-clone: ^1.5.13 influx: ^5.9.3 @@ -17410,8 +17410,8 @@ asn1@evs-broadcast/node-asn1: resolution: "mos-gateway@workspace:mos-gateway" dependencies: "@mos-connection/connector": 4.1.1 - "@sofie-automation/server-core-integration": 1.51.1-2 - "@sofie-automation/shared-lib": 1.51.1-2 + "@sofie-automation/server-core-integration": 1.51.1 + "@sofie-automation/shared-lib": 1.51.1 tslib: ^2.6.2 type-fest: ^3.13.1 underscore: ^1.13.6 @@ -19397,8 +19397,8 @@ asn1@evs-broadcast/node-asn1: version: 0.0.0-use.local resolution: "playout-gateway@workspace:playout-gateway" dependencies: - "@sofie-automation/server-core-integration": 1.51.1-2 - "@sofie-automation/shared-lib": 1.51.1-2 + "@sofie-automation/server-core-integration": 1.51.1 + "@sofie-automation/shared-lib": 1.51.1 debug: ^4.3.4 influx: ^5.9.3 timeline-state-resolver: 9.2.1 From 5d72c14f79aba87398d222c27e004e9a096375be Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 15 Nov 2024 14:04:48 +0100 Subject: [PATCH 06/30] chore: move checkForMultipleVersions into a yarn script --- .github/workflows/node.yaml | 2 +- package.json | 3 ++- scripts/checkForMultipleVersions.mjs | 17 ++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/node.yaml b/.github/workflows/node.yaml index fb50334747..ae6d82fd6f 100644 --- a/.github/workflows/node.yaml +++ b/.github/workflows/node.yaml @@ -748,6 +748,6 @@ jobs: CI: true - name: Run check run: | - node scripts/checkForMultipleVersions.mjs + yarn validate:versions env: CI: true diff --git a/package.json b/package.json index e232a83b9f..ac8dc02608 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,10 @@ "meteor:run": "cd meteor && meteor yarn start", "lint": "run lint:meteor && run lint:packages", "unit": "run unit:meteor && run unit:packages", - "validate:release": "yarn install && run install-and-build && run validate:release:packages && run validate:release:meteor", + "validate:release": "yarn install && run install-and-build && run validate:versions && run validate:release:packages && run validate:release:meteor", "validate:release:meteor": "cd meteor && meteor yarn validate:prod-dependencies && meteor yarn license-validate && meteor yarn lint && meteor yarn test", "validate:release:packages": "cd packages && run validate:dependencies && run test", + "validate:versions": "node scripts/checkForMultipleVersions.mjs", "meteor": "cd meteor && meteor", "docs:serve": "cd packages && run docs:serve", "reset": "node scripts/reset.mjs", diff --git a/scripts/checkForMultipleVersions.mjs b/scripts/checkForMultipleVersions.mjs index b633852235..792aee1f79 100644 --- a/scripts/checkForMultipleVersions.mjs +++ b/scripts/checkForMultipleVersions.mjs @@ -1,5 +1,12 @@ import { buildDepTreeFromFiles } from "snyk-nodejs-lockfile-parser"; +function hr() { + // write regular dashes if this is a "simple" output stream () + if (!process.stdout.hasColors || !process.stdout.hasColors()) + return "-".repeat(process.stdout.columns ?? 40); + return '─'.repeat(process.stdout.columns ?? 40) +} + /** * These are the libs we want to consider. * Its an array of arrays, to allow for multiple names to be treated as one package @@ -58,6 +65,10 @@ await addDepsForRoot("./packages", "live-status-gateway"); let hasFailure = false; +console.log(hr()) +console.log(" 🔢 Checking dependency version consistency...") +console.log(hr()) + // check each library for (const libName of libsToConsider) { const allVersions = new Set(); @@ -73,11 +84,11 @@ for (const libName of libsToConsider) { // output some info const str = Array.from(allVersions).join(", "); if (allVersions.size === 0) { - console.log(`No versions of "${nameStr}" installed`); + console.log(`âť” No versions of "${nameStr}" installed`); } else if (allVersions.size === 1) { - console.log(`Single version of "${nameStr}" installed: ${str}`); + console.log(`âś… Single version of "${nameStr}" installed: ${str}`); } else { - console.error(`Multiple versions of "${nameStr}" installed: ${str}`); + console.error(`⚠️ Multiple versions of "${nameStr}" installed: ${str}`); hasFailure = true; } } From 96360510d78fcc9dbfd31a125d363aab272f8158 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 15 Nov 2024 15:01:36 +0100 Subject: [PATCH 07/30] fix: release scripts broken on Windows --- packages/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/package.json b/packages/package.json index c379c53211..b38fcdc147 100644 --- a/packages/package.json +++ b/packages/package.json @@ -17,7 +17,7 @@ "build": "lerna run build --ignore @sofie-automation/openapi", "build:try": "lerna run --no-bail build --ignore @sofie-automation/openapi", "watch": "lerna run --parallel build:main --ignore @sofie-automation/openapi -- --watch --preserveWatchOutput", - "stage-versions": "git add -u */package.json */CHANGELOG.md lerna.json yarn.lock", + "stage-versions": "git add -u \"*/package.json\" \"*/CHANGELOG.md\" lerna.json yarn.lock", "set-version": "lerna version --exact --no-changelog --no-git-tag-version --no-push --yes", "set-version-and-commit": "lerna version --exact --no-changelog --no-changelog --no-commit-hooks --force-publish='*' --no-push --yes", "set-version-and-changelog": "lerna version --exact --force-publish --conventional-commits --no-git-tag-version --no-push --yes", @@ -65,4 +65,4 @@ }, "name": "packages", "packageManager": "yarn@3.5.0" -} +} \ No newline at end of file From 87016c1103af1ad7356ba3d845cdfa22a8af0fe8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 06:32:05 +0000 Subject: [PATCH 08/30] chore(deps): bump slackapi/slack-github-action from 1.27.0 to 2.0.0 Bumps [slackapi/slack-github-action](https://github.com/slackapi/slack-github-action) from 1.27.0 to 2.0.0. - [Release notes](https://github.com/slackapi/slack-github-action/releases) - [Commits](https://github.com/slackapi/slack-github-action/compare/v1.27.0...v2.0.0) --- updated-dependencies: - dependency-name: slackapi/slack-github-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/trivy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 1b361d1978..77e543ec70 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -64,7 +64,7 @@ jobs: echo ${{ env.SUMMARY }} - name: Send Slack Notification - uses: slackapi/slack-github-action@v1.27.0 + uses: slackapi/slack-github-action@v2.0.0 with: payload: | { From 0319536ae2903c8bfccdde53c14edd83b653e645 Mon Sep 17 00:00:00 2001 From: Silje Enge Kristensen Date: Wed, 20 Nov 2024 10:23:40 +0100 Subject: [PATCH 09/30] ci: changes needed by v2.0.0 of slack github action --- .github/workflows/trivy.yml | 75 +++++++++++++++---------------------- 1 file changed, 30 insertions(+), 45 deletions(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 77e543ec70..a8441412e8 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -2,7 +2,7 @@ name: Scheduled Trivy Scan on: workflow_dispatch: schedule: - - cron: '0 10 * * 1' + - cron: "0 10 * * 1" jobs: trivy: @@ -23,7 +23,7 @@ jobs: with: image-ref: ghcr.io/nrkno/sofie-core-${{ matrix.image }}:latest format: json - output: '${{ matrix.image }}-trivy-scan-results.json' + output: "${{ matrix.image }}-trivy-scan-results.json" - name: Run Trivy vulnerability scanner (table) uses: aquasecurity/trivy-action@0.28.0 @@ -31,7 +31,7 @@ jobs: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: image-ref: ghcr.io/nrkno/sofie-core-${{ matrix.image }}:latest - output: '${{ matrix.image }}-trivy-scan-results.txt' + output: "${{ matrix.image }}-trivy-scan-results.txt" - name: Post all scan results to Github Summary as a table env: @@ -48,8 +48,8 @@ jobs: env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: - format: 'github' - output: 'dependency-results-${{ matrix.image }}.sbom.json' + format: "github" + output: "dependency-results-${{ matrix.image }}.sbom.json" image-ref: ghcr.io/nrkno/sofie-core-${{ matrix.image }}:latest github-pat: ${{ secrets.GITHUB_TOKEN }} @@ -66,44 +66,29 @@ jobs: - name: Send Slack Notification uses: slackapi/slack-github-action@v2.0.0 with: + webhook: ${{ secrets.SLACK_WEBHOOK_URL }} + webhook-type: incoming-webhook payload: | - { - "text": "Trivy scan results", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "Trivy scan results for sofie-core-${{ matrix.image }}:latest" - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": ":thisisfine: ${{ env.SUMMARY }}" - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "Read the full scan results on Github" - }, - "accessory": { - "type": "button", - "text": { - "type": "plain_text", - "text": ":github: Scan results", - "emoji": true - }, - "value": "workflow_run", - "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", - "action_id": "button-action" - } - } - ] - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + text: "Trivy scan results" + blocks: + - type: "header" + text: + type: "plain_text" + text: "Trivy scan results for sofie-core-${{ matrix.image }}:latest" + - type: "section" + text: + type: "mrkdwn" + text: ":thisisfine: ${{ env.SUMMARY }}" + - type: "section" + text: + type: "mrkdwn" + text: "Read the full scan results on Github" + accessory: + type: "button" + text: + type: "plain_text" + text: ":github: Scan results" + emoji: true + value: "workflow_run" + url: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + action_id: "button-action" From e266bf2cff9c46f634e8ee77f9fcbd4a714eed98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 06:31:59 +0000 Subject: [PATCH 10/30] chore(deps): bump codecov/codecov-action from 4 to 5 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4...v5) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/node.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/node.yaml b/.github/workflows/node.yaml index 8811dc442d..99012a29bf 100644 --- a/.github/workflows/node.yaml +++ b/.github/workflows/node.yaml @@ -90,7 +90,7 @@ jobs: CI: true - name: Send coverage if: ((github.event_name == 'pull_request') && (!startsWith(github.head_ref, 'release'))) || ((github.event_name == 'push') && (!startsWith(github.ref_name, 'release'))) - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} @@ -525,7 +525,7 @@ jobs: CI: true - name: Send coverage if: (matrix.node-version == '16.x' || matrix.send-coverage == true) && ((github.event_name == 'pull_request') && ((!startsWith(github.head_ref, 'release'))) || ((github.event_name == 'push') && (!startsWith(github.ref_name, 'release')))) - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} From 1330f65d91ea67be2938f119281e4fa5c30930ac Mon Sep 17 00:00:00 2001 From: Johan Nyman Date: Wed, 13 Nov 2024 09:00:17 +0100 Subject: [PATCH 11/30] chore: improve logging in logAnyRemainingNowTimes --- .../src/playout/timeline/generate.ts | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/packages/job-worker/src/playout/timeline/generate.ts b/packages/job-worker/src/playout/timeline/generate.ts index dfa69ca208..dd2a59a709 100644 --- a/packages/job-worker/src/playout/timeline/generate.ts +++ b/packages/job-worker/src/playout/timeline/generate.ts @@ -201,32 +201,31 @@ function preserveOrReplaceNowTimesInObjects( } function logAnyRemainingNowTimes(_context: JobContext, timelineObjs: Array): void { - const ids: string[] = [] - - const hasNow = (obj: TimelineEnableExt | TimelineEnableExt[]) => { - let res = false - applyToArray(obj, (enable) => { - if (enable.start === 'now' || enable.end === 'now') res = true - }) - return res - } + const badTimelineObjs: any[] = [] for (const obj of timelineObjs) { if (hasNow(obj.enable)) { - ids.push(obj.id) + badTimelineObjs.push(obj) } for (const kf of obj.keyframes || []) { if (hasNow(kf.enable)) { - ids.push(kf.id) + badTimelineObjs.push(kf) } } } - if (ids.length) { - logger.error(`Some timeline objects have unexpected now times!: ${JSON.stringify(ids)}`) + if (badTimelineObjs.length) { + logger.error(`Some timeline objects have unexpected now times!: ${JSON.stringify(badTimelineObjs)}`) } } +function hasNow(obj: TimelineEnableExt | TimelineEnableExt[]) { + let res = false + applyToArray(obj, (enable) => { + if (enable.start === 'now' || enable.end === 'now') res = true + }) + return res +} /** Store the timelineobjects into the model, and perform any post-save actions */ export function saveTimeline( From 449abf949680c9f7841c8f268ece68e27c2ff918 Mon Sep 17 00:00:00 2001 From: Johan Nyman Date: Wed, 13 Nov 2024 10:37:19 +0100 Subject: [PATCH 12/30] chore: improve logging, for troubleshooting --- packages/job-worker/src/playout/infinites.ts | 22 ++++++++++++++- .../model/implementation/LoadPlayoutModel.ts | 28 +++++++++++++------ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/packages/job-worker/src/playout/infinites.ts b/packages/job-worker/src/playout/infinites.ts index 5924cb4a5c..222791d0f1 100644 --- a/packages/job-worker/src/playout/infinites.ts +++ b/packages/job-worker/src/playout/infinites.ts @@ -23,6 +23,7 @@ import { SegmentOrphanedReason } from '@sofie-automation/corelib/dist/dataModel/ import { sortRundownIDsInPlaylist } from '@sofie-automation/corelib/dist/playout/playlist' import { mongoWhere } from '@sofie-automation/corelib/dist/mongo' import { PlayoutRundownModel } from './model/PlayoutRundownModel' +import { logger } from '../logging' /** When we crop a piece, set the piece as "it has definitely ended" this far into the future. */ export const DEFINITELY_ENDED_FUTURE_DURATION = 1 * 1000 @@ -330,7 +331,26 @@ export function getPieceInstancesForPart( if (!playingRundown) throw new Error(`Rundown "${playingPartInstance.partInstance.rundownId}" not found!`) playingSegment = playingRundown.getSegment(playingPartInstance.partInstance.segmentId) - if (!playingSegment) throw new Error(`Segment "${playingPartInstance.partInstance.segmentId}" not found!`) + if (!playingSegment) { + const rundownId = playingRundown.rundown._id + context.directCollections.Segments.findFetch({ + rundownId: rundownId, + }) + .then((segment) => { + logger.error( + `TROUBLESHOOT: Segment not found, rundown "${rundownId}", segments in db: ${JSON.stringify( + segment.map((s) => s._id) + )}` + ) + }) + .catch((e) => logger.error(e)) + + throw new Error( + `Segment "${playingPartInstance.partInstance.segmentId}" in Rundown "${ + playingRundown.rundown._id + }" not found! (other segments: ${JSON.stringify(playingRundown.segments.map((s) => s.segment._id))})` + ) + } } const segment = rundown.getSegment(part.segmentId) diff --git a/packages/job-worker/src/playout/model/implementation/LoadPlayoutModel.ts b/packages/job-worker/src/playout/model/implementation/LoadPlayoutModel.ts index 20db14e685..8f0fcb70ca 100644 --- a/packages/job-worker/src/playout/model/implementation/LoadPlayoutModel.ts +++ b/packages/job-worker/src/playout/model/implementation/LoadPlayoutModel.ts @@ -23,6 +23,7 @@ import { PlayoutModel, PlayoutModelPreInit } from '../PlayoutModel' import { DBPart } from '@sofie-automation/corelib/dist/dataModel/Part' import { RundownBaselineObj } from '@sofie-automation/corelib/dist/dataModel/RundownBaselineObj' import { sortRundownsWithinPlaylist } from '@sofie-automation/corelib/dist/playout/playlist' +import { logger } from '../../../logging' /** * Load a PlayoutModelPreInit for the given RundownPlaylist @@ -188,7 +189,7 @@ async function loadRundowns( context.directCollections.Segments.findFetch({ $or: [ { - // In a different rundown + // Either in rundown when ingestModel === null or not available in ingestModel rundownId: { $in: loadRundownIds }, }, { @@ -233,14 +234,25 @@ async function loadRundowns( } } - return rundowns.map( - (rundown) => - new PlayoutRundownModelImpl( - rundown, - groupedSegmentsWithParts.get(rundown._id) ?? [], - groupedBaselineObjects.get(rundown._id) ?? [] + return rundowns.map((rundown) => { + const groupedSegmentsWithPartsForRundown = groupedSegmentsWithParts.get(rundown._id) + if (!groupedSegmentsWithPartsForRundown) { + logger.debug( + `groupedSegmentsWithPartsForRundown for Rundown "${rundown._id}" is undefined (has the rundown no segments?)` ) - ) + } + const groupedBaselineObjectsForRundown = groupedBaselineObjects.get(rundown._id) + if (!groupedBaselineObjectsForRundown) + logger.debug( + `groupedBaselineObjectsForRundown for Rundown "${rundown._id}" is undefined (has the rundown no baseline objects?)` + ) + + return new PlayoutRundownModelImpl( + rundown, + groupedSegmentsWithPartsForRundown ?? [], + groupedBaselineObjectsForRundown ?? [] + ) + }) } async function loadPartInstances( From 2c113b58b205198d13f0fc7e2114704311eb915b Mon Sep 17 00:00:00 2001 From: Johan Nyman Date: Wed, 13 Nov 2024 11:59:48 +0100 Subject: [PATCH 13/30] fix: Include previousPartInstance in check to orphan segments rather than remove them. This is because previousPartInstances are used in syncChangesToPartInstances --- packages/job-worker/src/ingest/commit.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/job-worker/src/ingest/commit.ts b/packages/job-worker/src/ingest/commit.ts index f315ee77cd..257044362f 100644 --- a/packages/job-worker/src/ingest/commit.ts +++ b/packages/job-worker/src/ingest/commit.ts @@ -259,10 +259,16 @@ export async function CommitIngestOperation( } function canRemoveSegment( + prevPartInstance: ReadonlyDeep | undefined, currentPartInstance: ReadonlyDeep | undefined, nextPartInstance: ReadonlyDeep | undefined, segmentId: SegmentId ): boolean { + if (prevPartInstance?.segmentId === segmentId) { + // Don't allow removing an active rundown + logger.warn(`Not allowing removal of previous playing segment "${segmentId}", making segment unsynced instead`) + return false + } if ( currentPartInstance?.segmentId === segmentId || (nextPartInstance?.segmentId === segmentId && isTooCloseToAutonext(currentPartInstance, false)) @@ -662,7 +668,7 @@ async function removeSegments( _changedSegmentIds: ReadonlyDeep, removedSegmentIds: ReadonlyDeep ) { - const { currentPartInstance, nextPartInstance } = await getSelectedPartInstances( + const { previousPartInstance, currentPartInstance, nextPartInstance } = await getSelectedPartInstances( context, newPlaylist, rundownsInPlaylist.map((r) => r._id) @@ -672,7 +678,7 @@ async function removeSegments( const orphanDeletedSegmentIds = new Set() const orphanHiddenSegmentIds = new Set() for (const segmentId of removedSegmentIds) { - if (canRemoveSegment(currentPartInstance, nextPartInstance, segmentId)) { + if (canRemoveSegment(previousPartInstance, currentPartInstance, nextPartInstance, segmentId)) { purgeSegmentIds.add(segmentId) } else { logger.warn( @@ -685,7 +691,7 @@ async function removeSegments( for (const segment of ingestModel.getAllSegments()) { const segmentId = segment.segment._id if (segment.segment.isHidden) { - if (!canRemoveSegment(currentPartInstance, nextPartInstance, segmentId)) { + if (!canRemoveSegment(previousPartInstance, currentPartInstance, nextPartInstance, segmentId)) { // Protect live segment from being hidden logger.warn(`Cannot hide live segment ${segmentId}, it will be orphaned`) switch (segment.segment.orphaned) { @@ -706,7 +712,7 @@ async function removeSegments( } else if (!orphanDeletedSegmentIds.has(segmentId) && segment.parts.length === 0) { // No parts in segment - if (!canRemoveSegment(currentPartInstance, nextPartInstance, segmentId)) { + if (!canRemoveSegment(previousPartInstance, currentPartInstance, nextPartInstance, segmentId)) { // Protect live segment from being hidden logger.warn(`Cannot hide live segment ${segmentId}, it will be orphaned`) orphanHiddenSegmentIds.add(segmentId) From 63a1d1751d5a6dbd331687bb937bc09ff7a9ea2f Mon Sep 17 00:00:00 2001 From: Johan Nyman Date: Wed, 13 Nov 2024 12:00:19 +0100 Subject: [PATCH 14/30] chore: log deleted documents, for troubleshooting --- .../implementation/DocumentChangeTracker.ts | 4 ++++ .../model/implementation/SaveIngestModel.ts | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/job-worker/src/ingest/model/implementation/DocumentChangeTracker.ts b/packages/job-worker/src/ingest/model/implementation/DocumentChangeTracker.ts index 7cf7d4bfbf..377784191c 100644 --- a/packages/job-worker/src/ingest/model/implementation/DocumentChangeTracker.ts +++ b/packages/job-worker/src/ingest/model/implementation/DocumentChangeTracker.ts @@ -94,6 +94,10 @@ export class DocumentChangeTracker }> { } } + getDeletedIds(): TDoc['_id'][] { + return Array.from(this.#deletedIds.values()) + } + /** * Generate the mongodb BulkWrite operations for the documents known to this tracker * @returns mongodb BulkWrite operations diff --git a/packages/job-worker/src/ingest/model/implementation/SaveIngestModel.ts b/packages/job-worker/src/ingest/model/implementation/SaveIngestModel.ts index c2995869cf..63dbd7fd7f 100644 --- a/packages/job-worker/src/ingest/model/implementation/SaveIngestModel.ts +++ b/packages/job-worker/src/ingest/model/implementation/SaveIngestModel.ts @@ -11,6 +11,8 @@ import { JobContext } from '../../../jobs' import { ExpectedPackagesStore } from './ExpectedPackagesStore' import { IngestSegmentModelImpl } from './IngestSegmentModelImpl' import { DocumentChangeTracker } from './DocumentChangeTracker' +import { logger } from '../../../logging' +import { ProtectedString } from '@sofie-automation/corelib/dist/protectedString' export class SaveIngestModelHelper { #expectedPackages = new DocumentChangeTracker() @@ -55,6 +57,23 @@ export class SaveIngestModelHelper { } commit(context: JobContext): Array> { + // Log deleted ids: + const deletedIds: { [key: string]: ProtectedString[] } = { + expectedPackages: this.#expectedPackages.getDeletedIds(), + expectedPlayoutItems: this.#expectedPlayoutItems.getDeletedIds(), + expectedMediaItems: this.#expectedMediaItems.getDeletedIds(), + segments: this.#segments.getDeletedIds(), + parts: this.#parts.getDeletedIds(), + pieces: this.#pieces.getDeletedIds(), + adLibPieces: this.#adLibPieces.getDeletedIds(), + adLibActions: this.#adLibActions.getDeletedIds(), + } + for (const [key, ids] of Object.entries[]>(deletedIds)) { + if (ids.length > 0) { + logger.debug(`Deleted ${key}: ${JSON.stringify(ids)} `) + } + } + return [ context.directCollections.ExpectedPackages.bulkWrite(this.#expectedPackages.generateWriteOps()), context.directCollections.ExpectedPlayoutItems.bulkWrite(this.#expectedPlayoutItems.generateWriteOps()), From bdab8c4e4ee1e67a3568cccc98106bb7f1258673 Mon Sep 17 00:00:00 2001 From: Johan Nyman Date: Thu, 14 Nov 2024 10:07:51 +0100 Subject: [PATCH 15/30] fix: updatePartInstancesSegmentIds: take into account when multiple segments have been merged into one. Also ensure that the bulkWrite uses a db index --- packages/job-worker/src/ingest/commit.ts | 88 ++++++++++++++++-------- 1 file changed, 61 insertions(+), 27 deletions(-) diff --git a/packages/job-worker/src/ingest/commit.ts b/packages/job-worker/src/ingest/commit.ts index 257044362f..7eccb296d6 100644 --- a/packages/job-worker/src/ingest/commit.ts +++ b/packages/job-worker/src/ingest/commit.ts @@ -43,6 +43,7 @@ import { DBPart } from '@sofie-automation/corelib/dist/dataModel/Part' import { DatabasePersistedModel } from '../modelBase' import { updateSegmentIdsForAdlibbedPartInstances } from './commit/updateSegmentIdsForAdlibbedPartInstances' import { stringifyError } from '@sofie-automation/shared-lib/dist/lib/stringifyError' +import { AnyBulkWriteOperation } from 'mongodb' export type BeforePartMapItem = { id: PartId; rank: number } export type BeforeIngestOperationPartMap = ReadonlyMap> @@ -301,26 +302,32 @@ async function updatePartInstancesSegmentIds( renamedSegments: ReadonlyMap | null, beforePartMap: BeforeIngestOperationPartMap ) { - // A set of rules which can be translated to mongo queries for PartInstances to update + /** + * Maps new SegmentId -> + * A set of rules which can be translated to mongo queries for PartInstances to update + */ const renameRules = new Map< SegmentId, { + /** Parts that have been moved to the new SegmentId */ partIds: PartId[] - fromSegmentId: SegmentId | null + /** Segments that have been renamed to the new SegmentId */ + fromSegmentIds: SegmentId[] } >() // Add whole segment renames to the set of rules if (renamedSegments) { for (const [fromSegmentId, toSegmentId] of renamedSegments) { - const rule = renameRules.get(toSegmentId) ?? { partIds: [], fromSegmentId: null } + const rule = renameRules.get(toSegmentId) ?? { partIds: [], fromSegmentIds: [] } renameRules.set(toSegmentId, rule) - rule.fromSegmentId = fromSegmentId + rule.fromSegmentIds.push(fromSegmentId) } } - // Reverse the structure + // Reverse the Map structure + /** Maps Part -> SegmentId-of-the-part-before-ingest-changes */ const beforePartSegmentIdMap = new Map() for (const [segmentId, partItems] of beforePartMap.entries()) { for (const partItem of partItems) { @@ -331,8 +338,11 @@ async function updatePartInstancesSegmentIds( // Some parts may have gotten a different segmentId to the base rule, so track those seperately in the rules for (const partModel of ingestModel.getAllOrderedParts()) { const oldSegmentId = beforePartSegmentIdMap.get(partModel.part._id) + if (oldSegmentId && oldSegmentId !== partModel.part.segmentId) { - const rule = renameRules.get(partModel.part.segmentId) ?? { partIds: [], fromSegmentId: null } + // The part has moved to another segment, add a rule to update its corresponding PartInstances: + + const rule = renameRules.get(partModel.part.segmentId) ?? { partIds: [], fromSegmentIds: [] } renameRules.set(partModel.part.segmentId, rule) rule.partIds.push(partModel.part._id) @@ -341,30 +351,52 @@ async function updatePartInstancesSegmentIds( // Perform a mongo update to modify the PartInstances if (renameRules.size > 0) { - await context.directCollections.PartInstances.bulkWrite( - Array.from(renameRules.entries()).map(([newSegmentId, rule]) => ({ - updateMany: { - filter: { - $or: _.compact([ - rule.fromSegmentId - ? { - segmentId: rule.fromSegmentId, - } - : undefined, - { - 'part._id': { $in: rule.partIds }, + const rulesInOrder = Array.from(renameRules.entries()).sort((a, b) => { + // Ensure that the ones with partIds are processed last, + // as that should take precedence. + + if (a[1].partIds.length && !b[1].partIds.length) return 1 + if (!a[1].partIds.length && b[1].partIds.length) return -1 + return 0 + }) + + const writeOps: AnyBulkWriteOperation[] = [] + + for (const [newSegmentId, rule] of rulesInOrder) { + if (rule.fromSegmentIds.length) { + writeOps.push({ + updateMany: { + filter: { + rundownId: ingestModel.rundownId, + segmentId: { $in: rule.fromSegmentIds }, + }, + update: { + $set: { + segmentId: newSegmentId, + 'part.segmentId': newSegmentId, }, - ]), + }, }, - update: { - $set: { - segmentId: newSegmentId, - 'part.segmentId': newSegmentId, + }) + } + if (rule.partIds.length) { + writeOps.push({ + updateMany: { + filter: { + rundownId: ingestModel.rundownId, + 'part._id': { $in: rule.partIds }, + }, + update: { + $set: { + segmentId: newSegmentId, + 'part.segmentId': newSegmentId, + }, }, }, - }, - })) - ) + }) + } + } + if (writeOps.length) await context.directCollections.PartInstances.bulkWrite(writeOps) } } @@ -691,8 +723,10 @@ async function removeSegments( for (const segment of ingestModel.getAllSegments()) { const segmentId = segment.segment._id if (segment.segment.isHidden) { + // Blueprints want to hide the Segment + if (!canRemoveSegment(previousPartInstance, currentPartInstance, nextPartInstance, segmentId)) { - // Protect live segment from being hidden + // The Segment is live, so we need to protect it from being hidden logger.warn(`Cannot hide live segment ${segmentId}, it will be orphaned`) switch (segment.segment.orphaned) { case SegmentOrphanedReason.DELETED: From 93f4b9de48e485eb098e2029752078501394f1fb Mon Sep 17 00:00:00 2001 From: Johan Nyman Date: Thu, 14 Nov 2024 10:08:25 +0100 Subject: [PATCH 16/30] chore: doc and logging for troubleshooting --- packages/corelib/src/dataModel/Segment.ts | 2 +- packages/job-worker/src/ingest/commit.ts | 31 +++++++++++++++++++ .../src/ingest/model/IngestSegmentModel.ts | 2 +- .../model/implementation/PlayoutModelImpl.ts | 28 ++++++++++++++--- 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/packages/corelib/src/dataModel/Segment.ts b/packages/corelib/src/dataModel/Segment.ts index 76996af431..a5f7c26e30 100644 --- a/packages/corelib/src/dataModel/Segment.ts +++ b/packages/corelib/src/dataModel/Segment.ts @@ -5,7 +5,7 @@ import { SegmentNote } from './Notes' export enum SegmentOrphanedReason { /** Segment is deleted from the NRCS but we still need it */ DELETED = 'deleted', - /** Segment should be hidden, but it is still playing */ + /** Blueprints want the Segment to be hidden, but it is still playing so is must not be hidden right now. */ HIDDEN = 'hidden', /** Segment is owned by playout, and is for AdlibTesting in its rundown */ ADLIB_TESTING = 'adlib-testing', diff --git a/packages/job-worker/src/ingest/commit.ts b/packages/job-worker/src/ingest/commit.ts index 7eccb296d6..83e09b6085 100644 --- a/packages/job-worker/src/ingest/commit.ts +++ b/packages/job-worker/src/ingest/commit.ts @@ -178,6 +178,9 @@ export async function CommitIngestOperation( // Ensure any adlibbed parts are updated to follow the segmentId of the previous part await updateSegmentIdsForAdlibbedPartInstances(context, ingestModel, beforePartMap) + if (data.renamedSegments && data.renamedSegments.size > 0) { + logger.debug(`Renamed segments: ${JSON.stringify(Array.from(data.renamedSegments.entries()))}`) + } // ensure instances have matching segmentIds with the parts await updatePartInstancesSegmentIds(context, ingestModel, data.renamedSegments, beforePartMap) @@ -397,6 +400,34 @@ async function updatePartInstancesSegmentIds( } } if (writeOps.length) await context.directCollections.PartInstances.bulkWrite(writeOps) + + // Double check that there are no parts using the old segment ids: + const oldSegmentIds = Array.from(renameRules.keys()) + const [badPartInstances, badParts] = await Promise.all([ + await context.directCollections.PartInstances.findFetch({ + rundownId: ingestModel.rundownId, + segmentId: { $in: oldSegmentIds }, + }), + await context.directCollections.Parts.findFetch({ + rundownId: ingestModel.rundownId, + segmentId: { $in: oldSegmentIds }, + }), + ]) + if (badPartInstances.length > 0) { + logger.error( + `updatePartInstancesSegmentIds: Failed to update all PartInstances using old SegmentIds "${JSON.stringify( + oldSegmentIds + )}": ${JSON.stringify(badPartInstances)}, writeOps: ${JSON.stringify(writeOps)}` + ) + } + + if (badParts.length > 0) { + logger.error( + `updatePartInstancesSegmentIds: Failed to update all Parts using old SegmentIds "${JSON.stringify( + oldSegmentIds + )}": ${JSON.stringify(badParts)}, writeOps: ${JSON.stringify(writeOps)}` + ) + } } } diff --git a/packages/job-worker/src/ingest/model/IngestSegmentModel.ts b/packages/job-worker/src/ingest/model/IngestSegmentModel.ts index d708cb5228..74010848d0 100644 --- a/packages/job-worker/src/ingest/model/IngestSegmentModel.ts +++ b/packages/job-worker/src/ingest/model/IngestSegmentModel.ts @@ -67,7 +67,7 @@ export interface IngestSegmentModel extends IngestSegmentModelReadonly { setOrphaned(orphaned: SegmentOrphanedReason | undefined): void /** - * Mark this Part as being hidden + * Mark this Segment as being hidden * @param hidden New hidden state */ setHidden(hidden: boolean): void diff --git a/packages/job-worker/src/playout/model/implementation/PlayoutModelImpl.ts b/packages/job-worker/src/playout/model/implementation/PlayoutModelImpl.ts index 6916022f36..b2d0508a08 100644 --- a/packages/job-worker/src/playout/model/implementation/PlayoutModelImpl.ts +++ b/packages/job-worker/src/playout/model/implementation/PlayoutModelImpl.ts @@ -751,12 +751,30 @@ export class PlayoutModelImpl extends PlayoutModelReadonlyImpl implements Playou if (this.rundownsImpl.find((rd) => rd.AdlibTestingSegmentHasChanged)) logOrThrowError(new Error(`Failed no changes in model assertion, an AdlibTesting Segment has been changed`)) - if ( - Array.from(this.allPartInstances.values()).find( - (part) => !part || part.partInstanceHasChanges || part.changedPieceInstanceIds().length > 0 - ) + const changedPartInstances = Array.from(this.allPartInstances.entries()).filter( + ([_, partInstance]) => + !partInstance || + partInstance.partInstanceHasChanges || + partInstance.changedPieceInstanceIds().length > 0 ) - logOrThrowError(new Error(`Failed no changes in model assertion, a PartInstance has been changed`)) + + if (changedPartInstances.length > 0) { + logOrThrowError( + new Error( + `Failed no changes in model assertion, PartInstances has been changed: ${JSON.stringify( + changedPartInstances.map( + ([id, pi]) => + `${id}: ` + + (!pi + ? 'null' + : `partInstanceHasChanges: ${ + pi.partInstanceHasChanges + }, changedPieceInstanceIds: ${JSON.stringify(pi.changedPieceInstanceIds())}`) + ) + )}` + ) + ) + } if (span) span.end() } From d976d00b93a46ffd1f32429ee3d6aa6df6fffddd Mon Sep 17 00:00:00 2001 From: Johan Nyman Date: Thu, 21 Nov 2024 11:55:48 +0100 Subject: [PATCH 17/30] chore(release): 1.51.2 --- meteor/CHANGELOG.md | 8 ++++ meteor/package.json | 2 +- meteor/yarn.lock | 12 +++--- packages/blueprints-integration/CHANGELOG.md | 8 ++++ packages/blueprints-integration/package.json | 4 +- packages/corelib/package.json | 6 +-- packages/documentation/package.json | 2 +- packages/job-worker/package.json | 8 ++-- packages/lerna.json | 2 +- packages/live-status-gateway/package.json | 10 ++--- packages/mos-gateway/CHANGELOG.md | 8 ++++ packages/mos-gateway/package.json | 6 +-- packages/openapi/package.json | 2 +- packages/playout-gateway/CHANGELOG.md | 8 ++++ packages/playout-gateway/package.json | 6 +-- packages/server-core-integration/CHANGELOG.md | 8 ++++ packages/server-core-integration/package.json | 4 +- packages/shared-lib/package.json | 2 +- packages/yarn.lock | 38 +++++++++---------- 19 files changed, 92 insertions(+), 52 deletions(-) diff --git a/meteor/CHANGELOG.md b/meteor/CHANGELOG.md index 7a08165001..be59164e1b 100644 --- a/meteor/CHANGELOG.md +++ b/meteor/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [1.51.2](https://github.com/nrkno/tv-automation-server-core/compare/v1.51.1...v1.51.2) (2024-11-21) + + +### Bug Fixes + +* Include previousPartInstance in check to orphan segments rather than remove them. ([2c113b5](https://github.com/nrkno/tv-automation-server-core/commit/2c113b58b205198d13f0fc7e2114704311eb915b)) +* updatePartInstancesSegmentIds: take into account when multiple segments have been merged into one. ([bdab8c4](https://github.com/nrkno/tv-automation-server-core/commit/bdab8c4e4ee1e67a3568cccc98106bb7f1258673)) + ## [1.51.0-in-testing.3](https://github.com/nrkno/sofie-core/compare/v1.51.0-in-testing.2...v1.51.0-in-testing.3) (2024-09-25) ## [1.51.0-in-testing.2](https://github.com/nrkno/sofie-core/compare/v1.51.0-in-testing.1...v1.51.0-in-testing.2) (2024-09-24) diff --git a/meteor/package.json b/meteor/package.json index ecffd16981..916bb3500c 100644 --- a/meteor/package.json +++ b/meteor/package.json @@ -1,6 +1,6 @@ { "name": "automation-core", - "version": "1.51.1", + "version": "1.51.2", "private": true, "engines": { "node": ">=14.19.1" diff --git a/meteor/yarn.lock b/meteor/yarn.lock index d3495e4ec4..57faed1ae1 100644 --- a/meteor/yarn.lock +++ b/meteor/yarn.lock @@ -1321,7 +1321,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@portal:../packages/blueprints-integration::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/shared-lib": 1.51.1 + "@sofie-automation/shared-lib": 1.51.2 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: node @@ -1362,8 +1362,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/corelib@portal:../packages/corelib::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/blueprints-integration": 1.51.1 - "@sofie-automation/shared-lib": 1.51.1 + "@sofie-automation/blueprints-integration": 1.51.2 + "@sofie-automation/shared-lib": 1.51.2 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -1394,9 +1394,9 @@ __metadata: resolution: "@sofie-automation/job-worker@portal:../packages/job-worker::locator=automation-core%40workspace%3A." dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.1 - "@sofie-automation/corelib": 1.51.1 - "@sofie-automation/shared-lib": 1.51.1 + "@sofie-automation/blueprints-integration": 1.51.2 + "@sofie-automation/corelib": 1.51.2 + "@sofie-automation/shared-lib": 1.51.2 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 diff --git a/packages/blueprints-integration/CHANGELOG.md b/packages/blueprints-integration/CHANGELOG.md index 2c8414a48b..324ca73cb6 100644 --- a/packages/blueprints-integration/CHANGELOG.md +++ b/packages/blueprints-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.2](https://github.com/nrkno/sofie-core/compare/v1.51.1...v1.51.2) (2024-11-21) + +**Note:** Version bump only for package @sofie-automation/blueprints-integration + + + + + ## [1.51.1](https://github.com/nrkno/sofie-core/compare/v1.51.1-2...v1.51.1) (2024-11-13) **Note:** Version bump only for package @sofie-automation/blueprints-integration diff --git a/packages/blueprints-integration/package.json b/packages/blueprints-integration/package.json index f29f8e3d83..cab45978f0 100644 --- a/packages/blueprints-integration/package.json +++ b/packages/blueprints-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/blueprints-integration", - "version": "1.51.1", + "version": "1.51.2", "description": "Library to define the interaction between core and the blueprints.", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -38,7 +38,7 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.1", + "@sofie-automation/shared-lib": "1.51.2", "tslib": "^2.6.2", "type-fest": "^3.13.1" }, diff --git a/packages/corelib/package.json b/packages/corelib/package.json index 49d556e657..c793597dea 100644 --- a/packages/corelib/package.json +++ b/packages/corelib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/corelib", - "version": "1.51.1", + "version": "1.51.2", "private": true, "description": "Internal library for some types shared by core and workers", "main": "dist/index.js", @@ -39,8 +39,8 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.1", - "@sofie-automation/shared-lib": "1.51.1", + "@sofie-automation/blueprints-integration": "1.51.2", + "@sofie-automation/shared-lib": "1.51.2", "fast-clone": "^1.5.13", "i18next": "^21.10.0", "influx": "^5.9.3", diff --git a/packages/documentation/package.json b/packages/documentation/package.json index 9e5367c3a7..846e1a879e 100644 --- a/packages/documentation/package.json +++ b/packages/documentation/package.json @@ -1,6 +1,6 @@ { "name": "sofie-documentation", - "version": "1.51.1", + "version": "1.51.2", "private": true, "scripts": { "docusaurus": "docusaurus", diff --git a/packages/job-worker/package.json b/packages/job-worker/package.json index c15e1e6ffd..763e8c6ff8 100644 --- a/packages/job-worker/package.json +++ b/packages/job-worker/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/job-worker", - "version": "1.51.1", + "version": "1.51.2", "description": "Worker for things", "main": "dist/index.js", "license": "MIT", @@ -41,9 +41,9 @@ ], "dependencies": { "@slack/webhook": "^6.1.0", - "@sofie-automation/blueprints-integration": "1.51.1", - "@sofie-automation/corelib": "1.51.1", - "@sofie-automation/shared-lib": "1.51.1", + "@sofie-automation/blueprints-integration": "1.51.2", + "@sofie-automation/corelib": "1.51.2", + "@sofie-automation/shared-lib": "1.51.2", "amqplib": "^0.10.3", "deepmerge": "^4.3.1", "elastic-apm-node": "^3.51.0", diff --git a/packages/lerna.json b/packages/lerna.json index d3ac537e86..3e4e29dc8d 100644 --- a/packages/lerna.json +++ b/packages/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.51.1", + "version": "1.51.2", "npmClient": "yarn", "useWorkspaces": true } diff --git a/packages/live-status-gateway/package.json b/packages/live-status-gateway/package.json index 6ffc183cba..e870b1b7b5 100644 --- a/packages/live-status-gateway/package.json +++ b/packages/live-status-gateway/package.json @@ -1,6 +1,6 @@ { "name": "live-status-gateway", - "version": "1.51.1", + "version": "1.51.2", "private": true, "description": "Provides state from Sofie over sockets", "license": "MIT", @@ -53,10 +53,10 @@ "production" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.1", - "@sofie-automation/corelib": "1.51.1", - "@sofie-automation/server-core-integration": "1.51.1", - "@sofie-automation/shared-lib": "1.51.1", + "@sofie-automation/blueprints-integration": "1.51.2", + "@sofie-automation/corelib": "1.51.2", + "@sofie-automation/server-core-integration": "1.51.2", + "@sofie-automation/shared-lib": "1.51.2", "debug": "^4.3.4", "fast-clone": "^1.5.13", "influx": "^5.9.3", diff --git a/packages/mos-gateway/CHANGELOG.md b/packages/mos-gateway/CHANGELOG.md index c8adfc4ea2..bdf4d9f8b8 100644 --- a/packages/mos-gateway/CHANGELOG.md +++ b/packages/mos-gateway/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.2](https://github.com/nrkno/sofie-core/compare/v1.51.1...v1.51.2) (2024-11-21) + +**Note:** Version bump only for package mos-gateway + + + + + ## [1.51.1](https://github.com/nrkno/sofie-core/compare/v1.51.1-2...v1.51.1) (2024-11-13) **Note:** Version bump only for package mos-gateway diff --git a/packages/mos-gateway/package.json b/packages/mos-gateway/package.json index 6db3bd8572..898dbd2997 100644 --- a/packages/mos-gateway/package.json +++ b/packages/mos-gateway/package.json @@ -1,6 +1,6 @@ { "name": "mos-gateway", - "version": "1.51.1", + "version": "1.51.2", "private": true, "description": "MOS-Gateway for the Sofie project", "license": "MIT", @@ -66,8 +66,8 @@ ], "dependencies": { "@mos-connection/connector": "4.1.1", - "@sofie-automation/server-core-integration": "1.51.1", - "@sofie-automation/shared-lib": "1.51.1", + "@sofie-automation/server-core-integration": "1.51.2", + "@sofie-automation/shared-lib": "1.51.2", "tslib": "^2.6.2", "type-fest": "^3.13.1", "underscore": "^1.13.6", diff --git a/packages/openapi/package.json b/packages/openapi/package.json index 45d4c33902..2a28ef83b4 100644 --- a/packages/openapi/package.json +++ b/packages/openapi/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/openapi", - "version": "1.51.1", + "version": "1.51.2", "license": "MIT", "repository": { "type": "git", diff --git a/packages/playout-gateway/CHANGELOG.md b/packages/playout-gateway/CHANGELOG.md index 00c009e113..60c6f11ee1 100644 --- a/packages/playout-gateway/CHANGELOG.md +++ b/packages/playout-gateway/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.2](https://github.com/nrkno/sofie-core/compare/v1.51.1...v1.51.2) (2024-11-21) + +**Note:** Version bump only for package playout-gateway + + + + + ## [1.51.1](https://github.com/nrkno/sofie-core/compare/v1.51.1-2...v1.51.1) (2024-11-13) **Note:** Version bump only for package playout-gateway diff --git a/packages/playout-gateway/package.json b/packages/playout-gateway/package.json index 327e433748..a86aaf3535 100644 --- a/packages/playout-gateway/package.json +++ b/packages/playout-gateway/package.json @@ -1,6 +1,6 @@ { "name": "playout-gateway", - "version": "1.51.1", + "version": "1.51.2", "private": true, "description": "Connect to Core, play stuff", "license": "MIT", @@ -56,8 +56,8 @@ "production" ], "dependencies": { - "@sofie-automation/server-core-integration": "1.51.1", - "@sofie-automation/shared-lib": "1.51.1", + "@sofie-automation/server-core-integration": "1.51.2", + "@sofie-automation/shared-lib": "1.51.2", "debug": "^4.3.4", "influx": "^5.9.3", "timeline-state-resolver": "9.2.1", diff --git a/packages/server-core-integration/CHANGELOG.md b/packages/server-core-integration/CHANGELOG.md index d374832bf1..c54cb75b39 100644 --- a/packages/server-core-integration/CHANGELOG.md +++ b/packages/server-core-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.2](https://github.com/nrkno/sofie-core/compare/v1.51.1...v1.51.2) (2024-11-21) + +**Note:** Version bump only for package @sofie-automation/server-core-integration + + + + + ## [1.51.1](https://github.com/nrkno/sofie-core/compare/v1.51.1-2...v1.51.1) (2024-11-13) **Note:** Version bump only for package @sofie-automation/server-core-integration diff --git a/packages/server-core-integration/package.json b/packages/server-core-integration/package.json index c8db37a4e0..7c548191ed 100644 --- a/packages/server-core-integration/package.json +++ b/packages/server-core-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/server-core-integration", - "version": "1.51.1", + "version": "1.51.2", "description": "Library for connecting to Core", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -70,7 +70,7 @@ "production" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.1", + "@sofie-automation/shared-lib": "1.51.2", "ejson": "^2.2.3", "eventemitter3": "^4.0.7", "faye-websocket": "^0.11.4", diff --git a/packages/shared-lib/package.json b/packages/shared-lib/package.json index 8047b89da7..39e85ca042 100644 --- a/packages/shared-lib/package.json +++ b/packages/shared-lib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/shared-lib", - "version": "1.51.1", + "version": "1.51.2", "description": "Library for types & values shared by core, workers and gateways", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/packages/yarn.lock b/packages/yarn.lock index bf3167a4e3..32b8d0f27e 100644 --- a/packages/yarn.lock +++ b/packages/yarn.lock @@ -4565,11 +4565,11 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/blueprints-integration@1.51.1, @sofie-automation/blueprints-integration@workspace:blueprints-integration": +"@sofie-automation/blueprints-integration@1.51.2, @sofie-automation/blueprints-integration@workspace:blueprints-integration": version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@workspace:blueprints-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.1 + "@sofie-automation/shared-lib": 1.51.2 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: unknown @@ -4606,12 +4606,12 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/corelib@1.51.1, @sofie-automation/corelib@workspace:corelib": +"@sofie-automation/corelib@1.51.2, @sofie-automation/corelib@workspace:corelib": version: 0.0.0-use.local resolution: "@sofie-automation/corelib@workspace:corelib" dependencies: - "@sofie-automation/blueprints-integration": 1.51.1 - "@sofie-automation/shared-lib": 1.51.1 + "@sofie-automation/blueprints-integration": 1.51.2 + "@sofie-automation/shared-lib": 1.51.2 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -4642,9 +4642,9 @@ __metadata: resolution: "@sofie-automation/job-worker@workspace:job-worker" dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.1 - "@sofie-automation/corelib": 1.51.1 - "@sofie-automation/shared-lib": 1.51.1 + "@sofie-automation/blueprints-integration": 1.51.2 + "@sofie-automation/corelib": 1.51.2 + "@sofie-automation/shared-lib": 1.51.2 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 @@ -4674,11 +4674,11 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/server-core-integration@1.51.1, @sofie-automation/server-core-integration@workspace:server-core-integration": +"@sofie-automation/server-core-integration@1.51.2, @sofie-automation/server-core-integration@workspace:server-core-integration": version: 0.0.0-use.local resolution: "@sofie-automation/server-core-integration@workspace:server-core-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.1 + "@sofie-automation/shared-lib": 1.51.2 ejson: ^2.2.3 eventemitter3: ^4.0.7 faye-websocket: ^0.11.4 @@ -4688,7 +4688,7 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/shared-lib@1.51.1, @sofie-automation/shared-lib@workspace:shared-lib": +"@sofie-automation/shared-lib@1.51.2, @sofie-automation/shared-lib@workspace:shared-lib": version: 0.0.0-use.local resolution: "@sofie-automation/shared-lib@workspace:shared-lib" dependencies: @@ -15334,10 +15334,10 @@ asn1@evs-broadcast/node-asn1: "@asyncapi/generator": ^1.17.25 "@asyncapi/html-template": ^2.3.9 "@asyncapi/nodejs-ws-template": ^0.9.36 - "@sofie-automation/blueprints-integration": 1.51.1 - "@sofie-automation/corelib": 1.51.1 - "@sofie-automation/server-core-integration": 1.51.1 - "@sofie-automation/shared-lib": 1.51.1 + "@sofie-automation/blueprints-integration": 1.51.2 + "@sofie-automation/corelib": 1.51.2 + "@sofie-automation/server-core-integration": 1.51.2 + "@sofie-automation/shared-lib": 1.51.2 debug: ^4.3.4 fast-clone: ^1.5.13 influx: ^5.9.3 @@ -17410,8 +17410,8 @@ asn1@evs-broadcast/node-asn1: resolution: "mos-gateway@workspace:mos-gateway" dependencies: "@mos-connection/connector": 4.1.1 - "@sofie-automation/server-core-integration": 1.51.1 - "@sofie-automation/shared-lib": 1.51.1 + "@sofie-automation/server-core-integration": 1.51.2 + "@sofie-automation/shared-lib": 1.51.2 tslib: ^2.6.2 type-fest: ^3.13.1 underscore: ^1.13.6 @@ -19397,8 +19397,8 @@ asn1@evs-broadcast/node-asn1: version: 0.0.0-use.local resolution: "playout-gateway@workspace:playout-gateway" dependencies: - "@sofie-automation/server-core-integration": 1.51.1 - "@sofie-automation/shared-lib": 1.51.1 + "@sofie-automation/server-core-integration": 1.51.2 + "@sofie-automation/shared-lib": 1.51.2 debug: ^4.3.4 influx: ^5.9.3 timeline-state-resolver: 9.2.1 From b13ba2d60afb5a95314fcd217b4e63b4b5f241fa Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Thu, 21 Nov 2024 15:35:00 +0100 Subject: [PATCH 18/30] fix: change CMD in GHA Dockerfile --- packages/live-status-gateway/Dockerfile.circle | 2 +- packages/mos-gateway/Dockerfile.circle | 2 +- packages/playout-gateway/Dockerfile.circle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/live-status-gateway/Dockerfile.circle b/packages/live-status-gateway/Dockerfile.circle index 4c01a0391e..974fead09d 100644 --- a/packages/live-status-gateway/Dockerfile.circle +++ b/packages/live-status-gateway/Dockerfile.circle @@ -10,4 +10,4 @@ COPY shared-lib /opt/shared-lib COPY corelib /opt/corelib WORKDIR /opt/live-status-gateway -CMD ["yarn", "start"] +CMD ["node", "dist/index.js"] diff --git a/packages/mos-gateway/Dockerfile.circle b/packages/mos-gateway/Dockerfile.circle index e6789a9abc..8f2d445450 100644 --- a/packages/mos-gateway/Dockerfile.circle +++ b/packages/mos-gateway/Dockerfile.circle @@ -8,4 +8,4 @@ COPY server-core-integration /opt/server-core-integration COPY shared-lib /opt/shared-lib WORKDIR /opt/mos-gateway -CMD ["yarn", "start"] +CMD ["node", "dist/index.js"] diff --git a/packages/playout-gateway/Dockerfile.circle b/packages/playout-gateway/Dockerfile.circle index 89e32da5d8..3dc8d9470e 100644 --- a/packages/playout-gateway/Dockerfile.circle +++ b/packages/playout-gateway/Dockerfile.circle @@ -8,4 +8,4 @@ COPY server-core-integration /opt/server-core-integration COPY shared-lib /opt/shared-lib WORKDIR /opt/playout-gateway -CMD ["yarn", "start"] +CMD ["node", "dist/index.js"] From 0c622b54a49d179c99b9b700f1c6bc3224ff609c Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Thu, 21 Nov 2024 15:58:05 +0100 Subject: [PATCH 19/30] chore(release): 1.51.3 --- meteor/package.json | 2 +- packages/blueprints-integration/CHANGELOG.md | 8 ++++ packages/blueprints-integration/package.json | 4 +- packages/corelib/package.json | 6 +-- packages/documentation/package.json | 2 +- packages/job-worker/package.json | 8 ++-- packages/lerna.json | 2 +- packages/live-status-gateway/package.json | 10 ++--- packages/mos-gateway/CHANGELOG.md | 11 ++++++ packages/mos-gateway/package.json | 6 +-- packages/openapi/package.json | 2 +- packages/playout-gateway/CHANGELOG.md | 11 ++++++ packages/playout-gateway/package.json | 6 +-- packages/server-core-integration/CHANGELOG.md | 8 ++++ packages/server-core-integration/package.json | 4 +- packages/shared-lib/package.json | 2 +- packages/yarn.lock | 38 +++++++++---------- 17 files changed, 84 insertions(+), 46 deletions(-) diff --git a/meteor/package.json b/meteor/package.json index 916bb3500c..3e27c5e714 100644 --- a/meteor/package.json +++ b/meteor/package.json @@ -1,6 +1,6 @@ { "name": "automation-core", - "version": "1.51.2", + "version": "1.51.3", "private": true, "engines": { "node": ">=14.19.1" diff --git a/packages/blueprints-integration/CHANGELOG.md b/packages/blueprints-integration/CHANGELOG.md index 324ca73cb6..abf1b45e2d 100644 --- a/packages/blueprints-integration/CHANGELOG.md +++ b/packages/blueprints-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) + +**Note:** Version bump only for package @sofie-automation/blueprints-integration + + + + + ## [1.51.2](https://github.com/nrkno/sofie-core/compare/v1.51.1...v1.51.2) (2024-11-21) **Note:** Version bump only for package @sofie-automation/blueprints-integration diff --git a/packages/blueprints-integration/package.json b/packages/blueprints-integration/package.json index cab45978f0..fc71da3f4f 100644 --- a/packages/blueprints-integration/package.json +++ b/packages/blueprints-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/blueprints-integration", - "version": "1.51.2", + "version": "1.51.3", "description": "Library to define the interaction between core and the blueprints.", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -38,7 +38,7 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.2", + "@sofie-automation/shared-lib": "1.51.3", "tslib": "^2.6.2", "type-fest": "^3.13.1" }, diff --git a/packages/corelib/package.json b/packages/corelib/package.json index c793597dea..4ac419dab0 100644 --- a/packages/corelib/package.json +++ b/packages/corelib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/corelib", - "version": "1.51.2", + "version": "1.51.3", "private": true, "description": "Internal library for some types shared by core and workers", "main": "dist/index.js", @@ -39,8 +39,8 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.2", - "@sofie-automation/shared-lib": "1.51.2", + "@sofie-automation/blueprints-integration": "1.51.3", + "@sofie-automation/shared-lib": "1.51.3", "fast-clone": "^1.5.13", "i18next": "^21.10.0", "influx": "^5.9.3", diff --git a/packages/documentation/package.json b/packages/documentation/package.json index 846e1a879e..3e30e7ac85 100644 --- a/packages/documentation/package.json +++ b/packages/documentation/package.json @@ -1,6 +1,6 @@ { "name": "sofie-documentation", - "version": "1.51.2", + "version": "1.51.3", "private": true, "scripts": { "docusaurus": "docusaurus", diff --git a/packages/job-worker/package.json b/packages/job-worker/package.json index 763e8c6ff8..bbac4c7c60 100644 --- a/packages/job-worker/package.json +++ b/packages/job-worker/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/job-worker", - "version": "1.51.2", + "version": "1.51.3", "description": "Worker for things", "main": "dist/index.js", "license": "MIT", @@ -41,9 +41,9 @@ ], "dependencies": { "@slack/webhook": "^6.1.0", - "@sofie-automation/blueprints-integration": "1.51.2", - "@sofie-automation/corelib": "1.51.2", - "@sofie-automation/shared-lib": "1.51.2", + "@sofie-automation/blueprints-integration": "1.51.3", + "@sofie-automation/corelib": "1.51.3", + "@sofie-automation/shared-lib": "1.51.3", "amqplib": "^0.10.3", "deepmerge": "^4.3.1", "elastic-apm-node": "^3.51.0", diff --git a/packages/lerna.json b/packages/lerna.json index 3e4e29dc8d..74b8a3c69c 100644 --- a/packages/lerna.json +++ b/packages/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.51.2", + "version": "1.51.3", "npmClient": "yarn", "useWorkspaces": true } diff --git a/packages/live-status-gateway/package.json b/packages/live-status-gateway/package.json index e870b1b7b5..4397d3b2f3 100644 --- a/packages/live-status-gateway/package.json +++ b/packages/live-status-gateway/package.json @@ -1,6 +1,6 @@ { "name": "live-status-gateway", - "version": "1.51.2", + "version": "1.51.3", "private": true, "description": "Provides state from Sofie over sockets", "license": "MIT", @@ -53,10 +53,10 @@ "production" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.2", - "@sofie-automation/corelib": "1.51.2", - "@sofie-automation/server-core-integration": "1.51.2", - "@sofie-automation/shared-lib": "1.51.2", + "@sofie-automation/blueprints-integration": "1.51.3", + "@sofie-automation/corelib": "1.51.3", + "@sofie-automation/server-core-integration": "1.51.3", + "@sofie-automation/shared-lib": "1.51.3", "debug": "^4.3.4", "fast-clone": "^1.5.13", "influx": "^5.9.3", diff --git a/packages/mos-gateway/CHANGELOG.md b/packages/mos-gateway/CHANGELOG.md index bdf4d9f8b8..9a91703d98 100644 --- a/packages/mos-gateway/CHANGELOG.md +++ b/packages/mos-gateway/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) + + +### Bug Fixes + +* change CMD in GHA Dockerfile ([b13ba2d](https://github.com/nrkno/sofie-core/commit/b13ba2d60afb5a95314fcd217b4e63b4b5f241fa)) + + + + + ## [1.51.2](https://github.com/nrkno/sofie-core/compare/v1.51.1...v1.51.2) (2024-11-21) **Note:** Version bump only for package mos-gateway diff --git a/packages/mos-gateway/package.json b/packages/mos-gateway/package.json index 898dbd2997..e0085ca549 100644 --- a/packages/mos-gateway/package.json +++ b/packages/mos-gateway/package.json @@ -1,6 +1,6 @@ { "name": "mos-gateway", - "version": "1.51.2", + "version": "1.51.3", "private": true, "description": "MOS-Gateway for the Sofie project", "license": "MIT", @@ -66,8 +66,8 @@ ], "dependencies": { "@mos-connection/connector": "4.1.1", - "@sofie-automation/server-core-integration": "1.51.2", - "@sofie-automation/shared-lib": "1.51.2", + "@sofie-automation/server-core-integration": "1.51.3", + "@sofie-automation/shared-lib": "1.51.3", "tslib": "^2.6.2", "type-fest": "^3.13.1", "underscore": "^1.13.6", diff --git a/packages/openapi/package.json b/packages/openapi/package.json index 2a28ef83b4..a79735ff45 100644 --- a/packages/openapi/package.json +++ b/packages/openapi/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/openapi", - "version": "1.51.2", + "version": "1.51.3", "license": "MIT", "repository": { "type": "git", diff --git a/packages/playout-gateway/CHANGELOG.md b/packages/playout-gateway/CHANGELOG.md index 60c6f11ee1..560b526971 100644 --- a/packages/playout-gateway/CHANGELOG.md +++ b/packages/playout-gateway/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) + + +### Bug Fixes + +* change CMD in GHA Dockerfile ([b13ba2d](https://github.com/nrkno/sofie-core/commit/b13ba2d60afb5a95314fcd217b4e63b4b5f241fa)) + + + + + ## [1.51.2](https://github.com/nrkno/sofie-core/compare/v1.51.1...v1.51.2) (2024-11-21) **Note:** Version bump only for package playout-gateway diff --git a/packages/playout-gateway/package.json b/packages/playout-gateway/package.json index a86aaf3535..0d8e33c4fa 100644 --- a/packages/playout-gateway/package.json +++ b/packages/playout-gateway/package.json @@ -1,6 +1,6 @@ { "name": "playout-gateway", - "version": "1.51.2", + "version": "1.51.3", "private": true, "description": "Connect to Core, play stuff", "license": "MIT", @@ -56,8 +56,8 @@ "production" ], "dependencies": { - "@sofie-automation/server-core-integration": "1.51.2", - "@sofie-automation/shared-lib": "1.51.2", + "@sofie-automation/server-core-integration": "1.51.3", + "@sofie-automation/shared-lib": "1.51.3", "debug": "^4.3.4", "influx": "^5.9.3", "timeline-state-resolver": "9.2.1", diff --git a/packages/server-core-integration/CHANGELOG.md b/packages/server-core-integration/CHANGELOG.md index c54cb75b39..7dfd8d5ce6 100644 --- a/packages/server-core-integration/CHANGELOG.md +++ b/packages/server-core-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) + +**Note:** Version bump only for package @sofie-automation/server-core-integration + + + + + ## [1.51.2](https://github.com/nrkno/sofie-core/compare/v1.51.1...v1.51.2) (2024-11-21) **Note:** Version bump only for package @sofie-automation/server-core-integration diff --git a/packages/server-core-integration/package.json b/packages/server-core-integration/package.json index 7c548191ed..954e9f8f04 100644 --- a/packages/server-core-integration/package.json +++ b/packages/server-core-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/server-core-integration", - "version": "1.51.2", + "version": "1.51.3", "description": "Library for connecting to Core", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -70,7 +70,7 @@ "production" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.2", + "@sofie-automation/shared-lib": "1.51.3", "ejson": "^2.2.3", "eventemitter3": "^4.0.7", "faye-websocket": "^0.11.4", diff --git a/packages/shared-lib/package.json b/packages/shared-lib/package.json index 39e85ca042..22e2b6b7fc 100644 --- a/packages/shared-lib/package.json +++ b/packages/shared-lib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/shared-lib", - "version": "1.51.2", + "version": "1.51.3", "description": "Library for types & values shared by core, workers and gateways", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/packages/yarn.lock b/packages/yarn.lock index 32b8d0f27e..cf52fe25db 100644 --- a/packages/yarn.lock +++ b/packages/yarn.lock @@ -4565,11 +4565,11 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/blueprints-integration@1.51.2, @sofie-automation/blueprints-integration@workspace:blueprints-integration": +"@sofie-automation/blueprints-integration@1.51.3, @sofie-automation/blueprints-integration@workspace:blueprints-integration": version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@workspace:blueprints-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.2 + "@sofie-automation/shared-lib": 1.51.3 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: unknown @@ -4606,12 +4606,12 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/corelib@1.51.2, @sofie-automation/corelib@workspace:corelib": +"@sofie-automation/corelib@1.51.3, @sofie-automation/corelib@workspace:corelib": version: 0.0.0-use.local resolution: "@sofie-automation/corelib@workspace:corelib" dependencies: - "@sofie-automation/blueprints-integration": 1.51.2 - "@sofie-automation/shared-lib": 1.51.2 + "@sofie-automation/blueprints-integration": 1.51.3 + "@sofie-automation/shared-lib": 1.51.3 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -4642,9 +4642,9 @@ __metadata: resolution: "@sofie-automation/job-worker@workspace:job-worker" dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.2 - "@sofie-automation/corelib": 1.51.2 - "@sofie-automation/shared-lib": 1.51.2 + "@sofie-automation/blueprints-integration": 1.51.3 + "@sofie-automation/corelib": 1.51.3 + "@sofie-automation/shared-lib": 1.51.3 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 @@ -4674,11 +4674,11 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/server-core-integration@1.51.2, @sofie-automation/server-core-integration@workspace:server-core-integration": +"@sofie-automation/server-core-integration@1.51.3, @sofie-automation/server-core-integration@workspace:server-core-integration": version: 0.0.0-use.local resolution: "@sofie-automation/server-core-integration@workspace:server-core-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.2 + "@sofie-automation/shared-lib": 1.51.3 ejson: ^2.2.3 eventemitter3: ^4.0.7 faye-websocket: ^0.11.4 @@ -4688,7 +4688,7 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/shared-lib@1.51.2, @sofie-automation/shared-lib@workspace:shared-lib": +"@sofie-automation/shared-lib@1.51.3, @sofie-automation/shared-lib@workspace:shared-lib": version: 0.0.0-use.local resolution: "@sofie-automation/shared-lib@workspace:shared-lib" dependencies: @@ -15334,10 +15334,10 @@ asn1@evs-broadcast/node-asn1: "@asyncapi/generator": ^1.17.25 "@asyncapi/html-template": ^2.3.9 "@asyncapi/nodejs-ws-template": ^0.9.36 - "@sofie-automation/blueprints-integration": 1.51.2 - "@sofie-automation/corelib": 1.51.2 - "@sofie-automation/server-core-integration": 1.51.2 - "@sofie-automation/shared-lib": 1.51.2 + "@sofie-automation/blueprints-integration": 1.51.3 + "@sofie-automation/corelib": 1.51.3 + "@sofie-automation/server-core-integration": 1.51.3 + "@sofie-automation/shared-lib": 1.51.3 debug: ^4.3.4 fast-clone: ^1.5.13 influx: ^5.9.3 @@ -17410,8 +17410,8 @@ asn1@evs-broadcast/node-asn1: resolution: "mos-gateway@workspace:mos-gateway" dependencies: "@mos-connection/connector": 4.1.1 - "@sofie-automation/server-core-integration": 1.51.2 - "@sofie-automation/shared-lib": 1.51.2 + "@sofie-automation/server-core-integration": 1.51.3 + "@sofie-automation/shared-lib": 1.51.3 tslib: ^2.6.2 type-fest: ^3.13.1 underscore: ^1.13.6 @@ -19397,8 +19397,8 @@ asn1@evs-broadcast/node-asn1: version: 0.0.0-use.local resolution: "playout-gateway@workspace:playout-gateway" dependencies: - "@sofie-automation/server-core-integration": 1.51.2 - "@sofie-automation/shared-lib": 1.51.2 + "@sofie-automation/server-core-integration": 1.51.3 + "@sofie-automation/shared-lib": 1.51.3 debug: ^4.3.4 influx: ^5.9.3 timeline-state-resolver: 9.2.1 From 86ab131f662560ea6c9234ecde3cd5890420d416 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Thu, 21 Nov 2024 16:08:49 +0100 Subject: [PATCH 20/30] chore(release): 1.51.3 --- meteor/yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/meteor/yarn.lock b/meteor/yarn.lock index 57faed1ae1..a6f56b2e2b 100644 --- a/meteor/yarn.lock +++ b/meteor/yarn.lock @@ -1321,7 +1321,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@portal:../packages/blueprints-integration::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/shared-lib": 1.51.2 + "@sofie-automation/shared-lib": 1.51.3 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: node @@ -1362,8 +1362,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/corelib@portal:../packages/corelib::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/blueprints-integration": 1.51.2 - "@sofie-automation/shared-lib": 1.51.2 + "@sofie-automation/blueprints-integration": 1.51.3 + "@sofie-automation/shared-lib": 1.51.3 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -1394,9 +1394,9 @@ __metadata: resolution: "@sofie-automation/job-worker@portal:../packages/job-worker::locator=automation-core%40workspace%3A." dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.2 - "@sofie-automation/corelib": 1.51.2 - "@sofie-automation/shared-lib": 1.51.2 + "@sofie-automation/blueprints-integration": 1.51.3 + "@sofie-automation/corelib": 1.51.3 + "@sofie-automation/shared-lib": 1.51.3 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 From 0ae53c408d5a6c675fb193729e8ad03a48bc1bda Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Thu, 21 Nov 2024 16:56:53 +0100 Subject: [PATCH 21/30] fix: Live Status Gateway Dockerfile (regular) still uses yarn to start --- packages/live-status-gateway/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/live-status-gateway/Dockerfile b/packages/live-status-gateway/Dockerfile index c9b3548b45..bf5043af45 100644 --- a/packages/live-status-gateway/Dockerfile +++ b/packages/live-status-gateway/Dockerfile @@ -27,4 +27,4 @@ COPY --from=0 /opt/shared-lib /opt/shared-lib COPY --from=0 /opt/corelib /opt/corelib WORKDIR /opt/live-status-gateway -CMD ["yarn", "start"] +CMD ["node", "dist/index.js"] From 2b3e502db62ddc9b4f9882ecf83a477765e49158 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Mon, 25 Nov 2024 16:35:21 +0100 Subject: [PATCH 22/30] chore: update "Quick install" / Installing Sofie Server Core page --- .../installation/installing-sofie-server-core.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/documentation/docs/user-guide/installation/installing-sofie-server-core.md b/packages/documentation/docs/user-guide/installation/installing-sofie-server-core.md index 2a07e4c960..e7d7243427 100644 --- a/packages/documentation/docs/user-guide/installation/installing-sofie-server-core.md +++ b/packages/documentation/docs/user-guide/installation/installing-sofie-server-core.md @@ -22,7 +22,7 @@ version: '3.3' services: db: hostname: mongo - image: mongo:4.2.18 + image: mongo:4.4 restart: always entrypoint: ['/usr/bin/mongod', '--replSet', 'rs0', '--bind_ip_all'] # the healthcheck avoids the need to initiate the replica set @@ -39,7 +39,7 @@ services: core: hostname: core - image: sofietv/tv-automation-server-core:release37 + image: sofietv/tv-automation-server-core:release51 restart: always ports: - '3000:3000' # Same port as meteor uses by default @@ -57,7 +57,7 @@ services: - db playout-gateway: - image: sofietv/tv-automation-playout-gateway:release37 + image: sofietv/tv-automation-playout-gateway:release51 restart: always command: yarn start -host core -port 3000 -id playoutGateway0 networks: @@ -80,7 +80,7 @@ services: # - core # mos-gateway: - # image: sofietv/tv-automation-mos-gateway:release37 + # image: sofietv/tv-automation-mos-gateway:release51 # restart: always # ports: # - "10540:10540" # MOS Lower port From 00c01bb491d8155d004350144757cae591d077dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:57:20 +0000 Subject: [PATCH 23/30] chore(deps): bump aquasecurity/trivy-action from 0.28.0 to 0.29.0 Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.28.0 to 0.29.0. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.28.0...0.29.0) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/node.yaml | 4 ++-- .github/workflows/trivy.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/node.yaml b/.github/workflows/node.yaml index 99012a29bf..6acd7aaf9b 100644 --- a/.github/workflows/node.yaml +++ b/.github/workflows/node.yaml @@ -239,7 +239,7 @@ jobs: echo "image=$image" >> $GITHUB_OUTPUT - name: Trivy scanning if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true' && steps.ghcr-tag.outputs.tags != 0 - uses: aquasecurity/trivy-action@0.28.0 + uses: aquasecurity/trivy-action@0.29.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: @@ -390,7 +390,7 @@ jobs: echo "image=$image" >> $GITHUB_OUTPUT - name: Trivy scanning if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true' && steps.ghcr-tag.outputs.tags != 0 - uses: aquasecurity/trivy-action@0.28.0 + uses: aquasecurity/trivy-action@0.29.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index a8441412e8..885d015d92 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Run Trivy vulnerability scanner (json) - uses: aquasecurity/trivy-action@0.28.0 + uses: aquasecurity/trivy-action@0.29.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: @@ -26,7 +26,7 @@ jobs: output: "${{ matrix.image }}-trivy-scan-results.json" - name: Run Trivy vulnerability scanner (table) - uses: aquasecurity/trivy-action@0.28.0 + uses: aquasecurity/trivy-action@0.29.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: @@ -44,7 +44,7 @@ jobs: echo $CODE_BLOCK >> $GITHUB_STEP_SUMMARY - name: Run Trivy in GitHub SBOM mode and submit results to Dependency Graph - uses: aquasecurity/trivy-action@0.28.0 + uses: aquasecurity/trivy-action@0.29.0 env: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db with: From 73c73d645fe364e58e26c4564bbbddb5dd6dacbb Mon Sep 17 00:00:00 2001 From: Jonas Hummelstrand Date: Thu, 28 Nov 2024 15:04:33 +0100 Subject: [PATCH 24/30] Update further-reading.md Updated the broken link to the Sofie Slack channel. --- packages/documentation/docs/user-guide/further-reading.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/documentation/docs/user-guide/further-reading.md b/packages/documentation/docs/user-guide/further-reading.md index caea59f4f2..be17d15f67 100644 --- a/packages/documentation/docs/user-guide/further-reading.md +++ b/packages/documentation/docs/user-guide/further-reading.md @@ -10,7 +10,7 @@ description: This guide has a lot of links. Here they are all listed by section. - [Gateways](concepts-and-architecture.md#gateways) - [Blueprints](concepts-and-architecture.md#blueprints) -- Ask questions in the [Sofie Slack Channel](https://join.slack.com/t/sofietv/shared_invite/enQtNTk2Mzc3MTQ1NzAzLTJkZjMyMDg3OGM0YWU3MmU4YzBhZDAyZWI1YmJmNmRiYWQ1OTZjYTkzOTkzMTA2YTE1YjgxMmVkM2U1OGZlNWI) +- Ask questions in the [Sofie Slack Channel](https://sofietv.slack.com/join/shared_invite/zt-2bfz8l9lw-azLeDB55cvN2wvMgqL1alA#/shared-invite/email) ## Installation & Setup From 193815dccd92f1d86acff5b316bc0956b9e8f0e4 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 29 Nov 2024 16:43:15 +0100 Subject: [PATCH 25/30] fix: Device Action Studio Context gets lost, Adlib previews are unstable --- .../deviceTriggers/RundownContentObserver.ts | 8 +- .../StudioDeviceTriggerManager.ts | 280 +++++++++--------- meteor/server/api/deviceTriggers/observer.ts | 43 +-- .../lib/ReactiveCacheCollection.ts | 49 +++ 4 files changed, 225 insertions(+), 155 deletions(-) diff --git a/meteor/server/api/deviceTriggers/RundownContentObserver.ts b/meteor/server/api/deviceTriggers/RundownContentObserver.ts index 3758160320..e0d7dddcef 100644 --- a/meteor/server/api/deviceTriggers/RundownContentObserver.ts +++ b/meteor/server/api/deviceTriggers/RundownContentObserver.ts @@ -32,7 +32,7 @@ export class RundownContentObserver { #observers: Meteor.LiveQueryHandle[] = [] #cache: ContentCache #cancelCache: () => void - #cleanup: () => void = () => { + #cleanup: (() => void) | undefined = () => { throw new Error('RundownContentObserver.#cleanup has not been set!') } #disposed = false @@ -45,8 +45,11 @@ export class RundownContentObserver { ) { logger.silly(`Creating RundownContentObserver for playlist "${rundownPlaylistId}"`) const { cache, cancel: cancelCache } = createReactiveContentCache(() => { + if (this.#disposed) { + this.#cleanup?.() + return + } this.#cleanup = onChanged(cache) - if (this.#disposed) this.#cleanup() }, REACTIVITY_DEBOUNCE) this.#cache = cache @@ -157,5 +160,6 @@ export class RundownContentObserver { this.#cancelCache() this.#observers.forEach((observer) => observer.stop()) this.#cleanup?.() + this.#cleanup = undefined } } diff --git a/meteor/server/api/deviceTriggers/StudioDeviceTriggerManager.ts b/meteor/server/api/deviceTriggers/StudioDeviceTriggerManager.ts index fc1b6ac0c2..bc3f205a82 100644 --- a/meteor/server/api/deviceTriggers/StudioDeviceTriggerManager.ts +++ b/meteor/server/api/deviceTriggers/StudioDeviceTriggerManager.ts @@ -38,20 +38,23 @@ export class StudioDeviceTriggerManager { StudioActionManagers.set(studioId, new StudioActionManager()) } - updateTriggers(cache: ContentCache, showStyleBaseId: ShowStyleBaseId): void { + async updateTriggers(cache: ContentCache, showStyleBaseId: ShowStyleBaseId): Promise { const studioId = this.studioId this.#lastShowStyleBaseId = showStyleBaseId - const rundownPlaylist = cache.RundownPlaylists.findOne({ - activationId: { - $exists: true, - }, - }) - if (!rundownPlaylist) { + const [showStyleBase, rundownPlaylist] = await Promise.all([ + cache.ShowStyleBases.findOneAsync(showStyleBaseId), + cache.RundownPlaylists.findOneAsync({ + activationId: { + $exists: true, + }, + }), + ]) + if (!showStyleBase || !rundownPlaylist) { return } - const context = createCurrentContextFromCache(cache) + const context = await createCurrentContextFromCache(cache) const actionManager = StudioActionManagers.get(studioId) if (!actionManager) throw new Meteor.Error( @@ -60,18 +63,13 @@ export class StudioDeviceTriggerManager { ) actionManager.setContext(context) - const showStyleBase = cache.ShowStyleBases.findOne(showStyleBaseId) - if (!showStyleBase) { - return - } - const { obj: sourceLayers } = applyAndValidateOverrides(showStyleBase.sourceLayersWithOverrides) - const allTriggeredActions = cache.TriggeredActions.find({ + const allTriggeredActions = await cache.TriggeredActions.find({ showStyleBaseId: { $in: [showStyleBaseId, null], }, - }) + }).fetchAsync() const upsertedDeviceTriggerMountedActionIds: DeviceTriggerMountedActionId[] = [] const touchedActionIds: DeviceActionId[] = [] @@ -83,116 +81,126 @@ export class StudioDeviceTriggerManager { const addedPreviewIds: PreviewWrappedAdLibId[] = [] - Object.entries(triggeredAction.actions).forEach(([key, action]) => { - // Since the compiled action is cached using this actionId as a key, having the action - // and the filterChain allows for a quicker invalidation without doing a deepEquals - const actionId = protectString( - `${studioId}_${triggeredAction._id}_${key}_${JSON.stringify(action)}` - ) - const existingAction = actionManager.getAction(actionId) - let thisAction: ExecutableAction - // Use the cached action or put a new one in the cache - if (existingAction) { - thisAction = existingAction - } else { - const compiledAction = createAction(action, sourceLayers) - actionManager.setAction(actionId, compiledAction) - thisAction = compiledAction - } - touchedActionIds.push(actionId) - - Object.entries(triggeredAction.triggers).forEach(([key, trigger]) => { - if (!isDeviceTrigger(trigger)) { - return + const updateActionsPromises = Object.entries(triggeredAction.actions).map( + async ([key, action]) => { + // Since the compiled action is cached using this actionId as a key, having the action + // and the filterChain allows for a quicker invalidation without doing a deepEquals + const actionId = protectString( + `${studioId}_${triggeredAction._id}_${key}_${JSON.stringify(action)}` + ) + const existingAction = actionManager.getAction(actionId) + let thisAction: ExecutableAction + // Use the cached action or put a new one in the cache + if (existingAction) { + thisAction = existingAction + } else { + const compiledAction = createAction(action, sourceLayers) + actionManager.setAction(actionId, compiledAction) + thisAction = compiledAction } + touchedActionIds.push(actionId) - let deviceActionArguments: ShiftRegisterActionArguments | undefined = undefined + const updateMountedActionsPromises = Object.entries( + triggeredAction.triggers + ).map(async ([key, trigger]) => { + if (!isDeviceTrigger(trigger)) { + return + } - if (action.action === DeviceActions.modifyShiftRegister) { - deviceActionArguments = { - type: 'modifyRegister', - register: action.register, - operation: action.operation, - value: action.value, - limitMin: action.limitMin, - limitMax: action.limitMax, + let deviceActionArguments: ShiftRegisterActionArguments | undefined = undefined + + if (action.action === DeviceActions.modifyShiftRegister) { + deviceActionArguments = { + type: 'modifyRegister', + register: action.register, + operation: action.operation, + value: action.value, + limitMin: action.limitMin, + limitMax: action.limitMax, + } } - } - const deviceTriggerMountedActionId = protectString( - `${actionId}_${key}` - ) - DeviceTriggerMountedActions.upsert(deviceTriggerMountedActionId, { - $set: { - studioId, - showStyleBaseId, - actionType: thisAction.action, - actionId, - deviceId: trigger.deviceId, - deviceTriggerId: trigger.triggerId, - values: trigger.values, - deviceActionArguments, - name: triggeredAction.name, - }, - }) - upsertedDeviceTriggerMountedActionIds.push(deviceTriggerMountedActionId) - }) - - if (!isPreviewableAction(thisAction)) { - const adLibPreviewId = protectString(`${actionId}_preview`) - DeviceTriggerMountedActionAdlibsPreview.upsert(adLibPreviewId, { - $set: literal({ - _id: adLibPreviewId, - _rank: 0, - partId: null, - type: undefined, - label: thisAction.action, - item: null, - triggeredActionId: triggeredAction._id, - actionId, - studioId, - showStyleBaseId, - sourceLayerType: undefined, - sourceLayerName: undefined, - styleClassNames: triggeredAction.styleClassNames, - }), + const deviceTriggerMountedActionId = protectString( + `${actionId}_${key}` + ) + upsertedDeviceTriggerMountedActionIds.push(deviceTriggerMountedActionId) + return DeviceTriggerMountedActions.upsertAsync(deviceTriggerMountedActionId, { + $set: { + studioId, + showStyleBaseId, + actionType: thisAction.action, + actionId, + deviceId: trigger.deviceId, + deviceTriggerId: trigger.triggerId, + values: trigger.values, + deviceActionArguments, + name: triggeredAction.name, + }, + }) }) - addedPreviewIds.push(adLibPreviewId) - } else { - const previewedAdLibs = thisAction.preview(context) + if (!isPreviewableAction(thisAction)) { + const adLibPreviewId = protectString(`${actionId}_preview`) - previewedAdLibs.forEach((adLib) => { - const adLibPreviewId = protectString( - `${triggeredAction._id}_${studioId}_${key}_${adLib._id}` - ) - DeviceTriggerMountedActionAdlibsPreview.upsert(adLibPreviewId, { + addedPreviewIds.push(adLibPreviewId) + await DeviceTriggerMountedActionAdlibsPreview.upsertAsync(adLibPreviewId, { $set: literal({ - ...adLib, _id: adLibPreviewId, + _rank: 0, + partId: null, + type: undefined, + label: thisAction.action, + item: null, triggeredActionId: triggeredAction._id, actionId, studioId, showStyleBaseId, - sourceLayerType: adLib.sourceLayerId - ? sourceLayers[adLib.sourceLayerId]?.type - : undefined, - sourceLayerName: adLib.sourceLayerId - ? { - name: sourceLayers[adLib.sourceLayerId]?.name, - abbreviation: sourceLayers[adLib.sourceLayerId]?.abbreviation, - } - : undefined, + sourceLayerType: undefined, + sourceLayerName: undefined, styleClassNames: triggeredAction.styleClassNames, }), }) + } else { + const previewedAdLibs = thisAction.preview(context) + + const previewedAdlibsUpdatePromises = previewedAdLibs.map(async (adLib) => { + const adLibPreviewId = protectString( + `${triggeredAction._id}_${studioId}_${key}_${adLib._id}` + ) + + addedPreviewIds.push(adLibPreviewId) + return DeviceTriggerMountedActionAdlibsPreview.upsertAsync(adLibPreviewId, { + $set: literal({ + ...adLib, + _id: adLibPreviewId, + triggeredActionId: triggeredAction._id, + actionId, + studioId, + showStyleBaseId, + sourceLayerType: adLib.sourceLayerId + ? sourceLayers[adLib.sourceLayerId]?.type + : undefined, + sourceLayerName: adLib.sourceLayerId + ? { + name: sourceLayers[adLib.sourceLayerId]?.name, + abbreviation: sourceLayers[adLib.sourceLayerId]?.abbreviation, + } + : undefined, + styleClassNames: triggeredAction.styleClassNames, + }), + }) + }) - addedPreviewIds.push(adLibPreviewId) - }) + await Promise.all(previewedAdlibsUpdatePromises) + } + + await Promise.all(updateMountedActionsPromises) } - }) + ) - DeviceTriggerMountedActionAdlibsPreview.remove({ + await Promise.all(updateActionsPromises) + + await DeviceTriggerMountedActionAdlibsPreview.removeAsync({ triggeredActionId: triggeredAction._id, _id: { $nin: addedPreviewIds, @@ -200,7 +208,7 @@ export class StudioDeviceTriggerManager { }) } - DeviceTriggerMountedActions.remove({ + await DeviceTriggerMountedActions.removeAsync({ studioId, showStyleBaseId, _id: { @@ -211,7 +219,7 @@ export class StudioDeviceTriggerManager { actionManager.deleteActionsOtherThan(touchedActionIds) } - clearTriggers(): void { + async clearTriggers(): Promise { const studioId = this.studioId const showStyleBaseId = this.#lastShowStyleBaseId @@ -226,28 +234,34 @@ export class StudioDeviceTriggerManager { `No Studio Action Manager available to handle action context in Studio "${studioId}"` ) - DeviceTriggerMountedActions.find({ + const mountedActions = await DeviceTriggerMountedActions.find({ studioId, showStyleBaseId, - }).forEach((mountedAction) => { + }).fetchAsync() + for (const mountedAction of mountedActions) { actionManager.deleteAction(mountedAction.actionId) - }) - DeviceTriggerMountedActions.remove({ - studioId, - showStyleBaseId, - }) - DeviceTriggerMountedActionAdlibsPreview.remove({ - studioId, - showStyleBaseId, - }) + } + + await Promise.all([ + DeviceTriggerMountedActions.removeAsync({ + studioId, + showStyleBaseId, + }), + DeviceTriggerMountedActionAdlibsPreview.removeAsync({ + studioId, + showStyleBaseId, + }), + ]) + actionManager.deleteContext() this.#lastShowStyleBaseId = null + return } - stop(): void { - this.clearTriggers() + async stop(): Promise { StudioActionManagers.delete(this.studioId) + return await this.clearTriggers() } } @@ -266,8 +280,8 @@ function convertDocument(doc: ReadonlyObjectDeep): UITrigger }) } -function createCurrentContextFromCache(cache: ContentCache): ReactivePlaylistActionContext { - const rundownPlaylist = cache.RundownPlaylists.findOne({ +async function createCurrentContextFromCache(cache: ContentCache): Promise { + const rundownPlaylist = await cache.RundownPlaylists.findOneAsync({ activationId: { $exists: true, }, @@ -275,24 +289,26 @@ function createCurrentContextFromCache(cache: ContentCache): ReactivePlaylistAct if (!rundownPlaylist) throw new Error('There should be an active RundownPlaylist!') - const currentPartInstance = rundownPlaylist.currentPartInfo - ? cache.PartInstances.findOne(rundownPlaylist.currentPartInfo.partInstanceId) - : undefined - const nextPartInstance = rundownPlaylist.nextPartInfo - ? cache.PartInstances.findOne(rundownPlaylist.nextPartInfo.partInstanceId) - : undefined + const [currentPartInstance, nextPartInstance] = await Promise.all([ + rundownPlaylist.currentPartInfo + ? cache.PartInstances.findOneAsync(rundownPlaylist.currentPartInfo.partInstanceId) + : undefined, + rundownPlaylist.nextPartInfo + ? cache.PartInstances.findOneAsync(rundownPlaylist.nextPartInfo.partInstanceId) + : undefined, + ]) const currentSegmentPartIds = currentPartInstance - ? cache.Parts.find({ + ? await cache.Parts.find({ segmentId: currentPartInstance.part.segmentId, - }).map((part) => part._id) + }).mapAsync((part) => part._id) : [] const nextSegmentPartIds = nextPartInstance ? nextPartInstance.part.segmentId === currentPartInstance?.part.segmentId ? currentSegmentPartIds - : cache.Parts.find({ + : await cache.Parts.find({ segmentId: nextPartInstance.part.segmentId, - }).map((part) => part._id) + }).mapAsync((part) => part._id) : [] return { diff --git a/meteor/server/api/deviceTriggers/observer.ts b/meteor/server/api/deviceTriggers/observer.ts index bcc7fa8853..ef3be0679c 100644 --- a/meteor/server/api/deviceTriggers/observer.ts +++ b/meteor/server/api/deviceTriggers/observer.ts @@ -29,28 +29,28 @@ Meteor.startup(() => { const studioObserversAndManagers = new Map() const jobQueue = new JobQueueWithClasses({ autoStart: true, - executionWrapper: Meteor.bindEnvironment, - resolutionWrapper: Meteor.defer, }) - function workInQueue(fnc: () => Promise) { - jobQueue.add(fnc).catch((e) => { - logger.error(`Error in DeviceTriggers Studio observer reaction: ${stringifyError(e)}`) - }) + function workInQueue(fnc: () => Promise) { + jobQueue + .add(async () => { + const res = await fnc() + return res + }) + .catch((e) => { + logger.error(`Error in DeviceTriggers Studio observer reaction: ${stringifyError(e)}`) + }) } function createObserverAndManager(studioId: StudioId) { logger.debug(`Creating observer for studio "${studioId}"`) const manager = new StudioDeviceTriggerManager(studioId) const observer = new StudioObserver(studioId, (showStyleBaseId, cache) => { - workInQueue(async () => { - manager.updateTriggers(cache, showStyleBaseId) - }) + logger.silly(`Studio observer updating triggers for "${studioId}":"${showStyleBaseId}"`) + workInQueue(async () => manager.updateTriggers(cache, showStyleBaseId)) return () => { - workInQueue(async () => { - manager.clearTriggers() - }) + workInQueue(async () => manager.clearTriggers()) } }) @@ -58,15 +58,16 @@ Meteor.startup(() => { } function destroyObserverAndManager(studioId: StudioId) { - logger.debug(`Destroying observer for studio "${studioId}"`) - const toRemove = studioObserversAndManagers.get(studioId) - if (toRemove) { - toRemove.observer.stop() - toRemove.manager.stop() - studioObserversAndManagers.delete(studioId) - } else { - logger.error(`Observer for studio "${studioId}" not found`) - } + workInQueue(async () => { + const toRemove = studioObserversAndManagers.get(studioId) + if (toRemove) { + toRemove.observer.stop() + await toRemove.manager.stop() + studioObserversAndManagers.delete(studioId) + } else { + logger.error(`Observer for studio "${studioId}" not found`) + } + }) } Studios.observeChanges( diff --git a/meteor/server/publications/lib/ReactiveCacheCollection.ts b/meteor/server/publications/lib/ReactiveCacheCollection.ts index 294430cab1..6b7df53a34 100644 --- a/meteor/server/publications/lib/ReactiveCacheCollection.ts +++ b/meteor/server/publications/lib/ReactiveCacheCollection.ts @@ -69,6 +69,55 @@ export class ReactiveCacheCollection, + options?: Omit, 'limit'> + ): Promise { + return this.#collection.findOne(selector as any, options) + } + + async insertAsync(doc: Mongo.OptionalId): Promise { + const id = await this.#collection.insertAsync(doc) + this.runReaction() + return id + } + + async removeAsync(selector: Document['_id'] | MongoQuery): Promise { + const num = await this.#collection.removeAsync(selector as any) + if (num > 0) { + this.runReaction() + } + return num + } + + async updateAsync( + selector: Document['_id'] | MongoQuery, + modifier: MongoModifier, + options?: { + multi?: boolean + upsert?: boolean + arrayFilters?: { [identifier: string]: any }[] + } + ): Promise { + const num = await this.#collection.updateAsync(selector as any, modifier as any, options) + if (num > 0) { + this.runReaction() + } + return num + } + + async upsertAsync( + selector: Document['_id'] | Mongo.Selector, + modifier: Mongo.Modifier, + options?: { multi?: boolean } + ): Promise<{ numberAffected?: number; insertedId?: string }> { + const res = await this.#collection.upsertAsync(selector as any, modifier as any, options) + if (res.numberAffected || res.insertedId) { + this.runReaction() + } + return res + } + link(cb?: () => void): ObserveChangesCallbacks { return { added: (id: Document['_id'], fields: Partial) => { From 0855c83c34c669f5dd38c06086b111b18c5d81fe Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 29 Nov 2024 17:28:25 +0100 Subject: [PATCH 26/30] chore: update suggested mongo to 6.0 --- .../user-guide/installation/installing-sofie-server-core.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/documentation/docs/user-guide/installation/installing-sofie-server-core.md b/packages/documentation/docs/user-guide/installation/installing-sofie-server-core.md index e7d7243427..9b3c1412d1 100644 --- a/packages/documentation/docs/user-guide/installation/installing-sofie-server-core.md +++ b/packages/documentation/docs/user-guide/installation/installing-sofie-server-core.md @@ -22,12 +22,12 @@ version: '3.3' services: db: hostname: mongo - image: mongo:4.4 + image: mongo:6.0 restart: always entrypoint: ['/usr/bin/mongod', '--replSet', 'rs0', '--bind_ip_all'] # the healthcheck avoids the need to initiate the replica set healthcheck: - test: test $$(echo "rs.initiate().ok || rs.status().ok" | mongo --quiet) -eq 1 + test: test $$(mongosh --quiet --eval "try {rs.initiate()} catch(e) {rs.status().ok}") -eq 1 interval: 10s start_period: 30s ports: From 276462cd07ac9773df85339852f26695c8dfb129 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 29 Nov 2024 17:33:10 +0100 Subject: [PATCH 27/30] chore: add snapshot of 1.50.x docs --- .../version-1.50.0/about-sofie.md | 22 ++ .../for-developers/api-documentation.md | 8 + .../for-developers/api-stability.md | 26 ++ .../for-developers/contribution-guidelines.md | 96 ++++++ .../for-developers/data-model.md | 132 ++++++++ .../device-integrations/_category_.json | 4 + .../device-integrations/intro.md | 18 + .../options-and-mappings.md | 11 + .../device-integrations/tsr-actions.md | 11 + .../device-integrations/tsr-api.md | 28 ++ .../device-integrations/tsr-types.md | 7 + .../for-blueprint-developers/_category_.json | 4 + .../_part-timings-demo.jsx | 173 ++++++++++ .../for-blueprint-developers/ab-playback.md | 236 +++++++++++++ .../for-blueprint-developers/hold.md | 52 +++ .../for-blueprint-developers/intro.md | 20 ++ .../for-blueprint-developers/lookahead.md | 96 ++++++ .../part-and-piece-timings.mdx | 141 ++++++++ .../sync-ingest-changes.md | 23 ++ .../timeline-datastore.md | 85 +++++ .../version-1.50.0/for-developers/intro.md | 15 + .../for-developers/json-config-schema.md | 209 ++++++++++++ .../for-developers/libraries.md | 62 ++++ .../for-developers/publications.md | 43 +++ .../worker-threads-and-locks.md | 61 ++++ .../user-guide/concepts-and-architecture.md | 192 +++++++++++ .../user-guide/configuration/_category_.json | 4 + .../user-guide/configuration/settings-view.md | 173 ++++++++++ .../configuration/sofie-core-settings.md | 111 +++++++ .../version-1.50.0/user-guide/faq.md | 17 + .../user-guide/features/_category_.json | 4 + .../user-guide/features/access-levels.md | 46 +++ .../version-1.50.0/user-guide/features/api.md | 19 ++ .../user-guide/features/language.md | 23 ++ .../user-guide/features/prompter.md | 189 +++++++++++ .../user-guide/features/sofie-views.mdx | 313 ++++++++++++++++++ .../user-guide/features/system-health.md | 27 ++ .../user-guide/further-reading.md | 59 ++++ .../user-guide/installation/_category_.json | 4 + .../installation/initial-sofie-core-setup.md | 23 ++ .../installing-a-gateway/_category_.json | 4 + .../installing-a-gateway/intro.md | 25 ++ .../installing-a-gateway/playout-gateway.md | 6 + .../_category_.json | 4 + .../inews-gateway.md | 12 + ...g-sofie-with-google-spreadsheet-support.md | 46 +++ .../intro.md | 14 + .../mos-gateway.md | 9 + .../installation/installing-blueprints.md | 46 +++ .../README.md | 35 ++ .../_category_.json | 4 + .../casparcg-server-installation.md | 233 +++++++++++++ .../ffmpeg-installation.md | 35 ++ .../vision-mixers.md | 14 + .../installation/installing-input-gateway.md | 34 ++ .../installing-package-manager.md | 93 ++++++ .../installing-sofie-server-core.md | 139 ++++++++ .../user-guide/installation/intro.md | 37 +++ .../user-guide/installation/media-manager.md | 21 ++ .../user-guide/installation/rundown-editor.md | 11 + .../version-1.50.0/user-guide/intro.md | 41 +++ .../user-guide/supported-devices.md | 118 +++++++ packages/documentation/versions.json | 15 +- 63 files changed, 3776 insertions(+), 7 deletions(-) create mode 100644 packages/documentation/versioned_docs/version-1.50.0/about-sofie.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/api-documentation.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/api-stability.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/contribution-guidelines.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/data-model.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/_category_.json create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/intro.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/options-and-mappings.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-actions.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-api.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-types.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/_category_.json create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/_part-timings-demo.jsx create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/ab-playback.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/hold.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/intro.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/lookahead.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/part-and-piece-timings.mdx create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/sync-ingest-changes.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/timeline-datastore.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/intro.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/json-config-schema.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/libraries.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/publications.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/for-developers/worker-threads-and-locks.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/concepts-and-architecture.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/_category_.json create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/settings-view.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/sofie-core-settings.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/faq.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/features/_category_.json create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/features/access-levels.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/features/api.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/features/language.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/features/prompter.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/features/sofie-views.mdx create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/features/system-health.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/further-reading.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/_category_.json create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/initial-sofie-core-setup.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/_category_.json create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/intro.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/playout-gateway.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/_category_.json create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/inews-gateway.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/installing-sofie-with-google-spreadsheet-support.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/intro.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/mos-gateway.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-blueprints.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/README.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/_category_.json create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/casparcg-server-installation.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/ffmpeg-installation.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/vision-mixers.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-input-gateway.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-package-manager.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-sofie-server-core.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/intro.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/media-manager.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/rundown-editor.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/intro.md create mode 100644 packages/documentation/versioned_docs/version-1.50.0/user-guide/supported-devices.md diff --git a/packages/documentation/versioned_docs/version-1.50.0/about-sofie.md b/packages/documentation/versioned_docs/version-1.50.0/about-sofie.md new file mode 100644 index 0000000000..363475f108 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/about-sofie.md @@ -0,0 +1,22 @@ +--- +title: About Sofie +hide_table_of_contents: true +sidebar_label: About Sofie +sidebar_position: 1 +--- + +# NRK Sofie TV Automation System + +![The producer's view in Sofie](https://raw.githubusercontent.com/nrkno/Sofie-TV-automation/master/images/Sofie_GUI_example.jpg) + +_**Sofie**_ is a web-based TV automation system for studios and live shows, used in daily live TV news productions by the Norwegian public service broadcaster [**NRK**](https://www.nrk.no/about/) since September 2018. + +## Key Features + +- User-friendly, modern web-based GUI +- State-based device control and playout of video, audio, and graphics +- Modular device-control architecture with support for several hardware \(and software\) setups +- Modular data-ingest architecture, supports MOS and Google spreadsheets +- Plug-in architecture for programming shows + +_The NRK logo is a registered trademark of Norsk rikskringkasting AS. The license does not grant any right to use, in any way, any trademarks, service marks or logos of Norsk rikskringkasting AS._ \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/api-documentation.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/api-documentation.md new file mode 100644 index 0000000000..9d5c84dee7 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/api-documentation.md @@ -0,0 +1,8 @@ +--- +sidebar_position: 6 +--- + +# API Documentation + +The Sofie Blueprints API and the Sofie Peripherals API documentation is automatically generated and available through +[nrkno.github.io/sofie-core/typedoc](https://nrkno.github.io/sofie-core/typedoc). diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/api-stability.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/api-stability.md new file mode 100644 index 0000000000..253a3bb750 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/api-stability.md @@ -0,0 +1,26 @@ +--- +title: API Stability +sidebar_position: 11 +--- + +Sofie has various APIs for talking between components, and for external systems to interact with. + +We classify each api into one of two categories: + +## Stable + +This is a collection of APIs which we intend to avoid introducing any breaking change to unless necessary. This is so external systems can rely on this API without needing to be updated in lockstep with Sofie, and hopefully will make sense to developers who are not familiar with Sofie's inner workings. + +In version 1.50, a new REST API was introduced. This can be found at `/api/v1.0`, and is designed to allow an external system to interact with Sofie using simplified abstractions of Sofie internals. + +The _Live Status Gateway_ is also part of this stable API, intended to allow for reactively retrieving data from Sofie. Internally it is translating the internal APIs into a stable version. + +:::note +You can find the _Live Status Gateway_ in the `packages` folder of the [Sofie Core](https://github.com/nrkno/sofie-core) repository. +::: + +## Internal + +This covers everything we expose over DDP, the `/api/0` endpoint and any other http endpoints. + +These are intended for use between components of Sofie, which should be updated together. The DDP api does have breaking changes in most releases. We use the `server-core-integration` library to manage these typings, and to ensure that compatible versions are used together. diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/contribution-guidelines.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/contribution-guidelines.md new file mode 100644 index 0000000000..4e6ffadc97 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/contribution-guidelines.md @@ -0,0 +1,96 @@ +--- +description: >- + The Sofie team happily encourage contributions to the Sofie project, and + kindly ask you to observe these guidelines when doing so. +sidebar_position: 2 +--- + +# Contribution Guidelines + +## About the Sofie TV Studio Automation Project + +The Sofie project includes a number of open source applications and libraries developed and maintained by the Norwegian public service broadcaster, [NRK](https://www.nrk.no/about/). Sofie has been used to produce live shows at NRK since September 2018. + +A list of the "Sofie repositories" [can be found here](libraries.md). NRK owns the copyright of the contents of the official Sofie repositories, including the source code, related files, as well as the Sofie logo. + +The Sofie team at NRK is responsible for development and maintenance. We also do thorough testing of each release to avoid regressions in functionality and ensure interoperability with the various hardware and software involved. + +The Sofie team welcomes open source contributions and will actively work towards enabling contributions to become mergeable into the Sofie repositories. However, as main stakeholder and maintainer we reserve the right to refuse any contributions. + + +## About Contributions + +Thank you for considering contributing to the Sofie project! + +Before you start, there are a few things you should know: + +### “Discussions Before Pull Requests” + +**Minor changes** (most bug fixes and small features) can be submitted directly as pull requests to the appropriate official repo. + +However, Sofie is a big project with many differing users and use cases. **Larger changes** might be more difficult to merge into an official repository if NRK has not been made aware of their existence beforehand. To facilitate a timely handling of larger contributions, there’s a workflow intended to keep an open dialogue between all interested parties: + +1. Contributor opens an RFC (as a _GitHub issue_) in the appropriate repository. +2. NRK evaluates the RFC, usually within a week. +3. (If needed) NRK establishes contact with the RFC author, who will be invited to a workshop where the RFC is discussed. Meeting notes are published publicly on the RFC thread. +4. The contributor references the RFC when a pull request is ready. + +### Base contributions on the in-development branch (or the master branch) +In order to facilitate merging, we ask that contributions are based on the latest (at the time of the pull request) _in-development_ branch (often named `release*`), alternatively the stable (eg. `master`) branch. NRK will take responsibility for rebasing stable contributions to the latest in-development branch if needed. +See **CONTRIBUTING.md** in each official repository for details on which branch to use as a base for contributions. + +## Developer Guidelines + +### Pull Requests + +We encourage you to open PRs early! If it’s still in development, open the PR as a draft. + +### Types + +All official Sofie repositories use TypeScript. When you contribute code, be sure to keep it as strictly typed as possible. + +### Code Style & Formatting + +Most of the projects use a linter (eslint) and a formatter (prettier). Before submitting a pull request, please make sure it conforms to the linting rules by running yarn lint. yarn lint --fix can fix most of the issues. + +### Documentation + +We rely on two types of documentation; the [Sofie documentation](https://nrkno.github.io/sofie-core/) ([source code](https://github.com/nrkno/sofie-core/tree/master/packages/documentation)) and inline code documentation. + +We don't aim to have the "absolute perfect documentation possible", BUT we do try to improve and add documentation to have a good-enough-to-be-comprehensible standard. We think that: + +* _What_ something does is not as important – we can read the code for that. +* _Why_ something does something, **is** important. Implied usage, side-effects, descriptions of the context etcetera... + +When you contribute, we ask you to also update any documentation where needed. + +### Updating Dependencies​ +When updating dependencies in a library, it is preferred to do so via `yarn upgrade-interactive --latest` whenever possible. This is so that the versions in `package.json` are also updated as we have no guarantee that the library will work with versions lower than that used in the `yarn.lock` file, even if it is compatible with the semver range in `package.json`. After this, a `yarn upgrade` can be used to update any child dependencies + +Be careful when bumping across major versions. + +Also, each of the libraries has a minimum nodejs version specified in their package.json. Care must be taken when updating dependencies to ensure its compatibility is retained. + +### Resolutions​ + +We sometimes use the `yarn resolutions` property in `package.json` to fix security vulnerabilities in dependencies of libraries that haven't released a fix yet. If adding a new one, try to make it as specific as possible to ensure it doesn't have unintended side effects. + +When updating other dependencies, it is a good idea to make sure that the resolutions defined still apply and are correct. + +### Logging + +When logging, we try to adher to the following guideliness: + +Usage of `console.log` and `console.error` directly is discouraged (except for quick debugging locally). Instead, use one of the logger libraries (to output json logs which are easier to index). +When logging, use one of the **log level** described below: + +| Level | Description | Examples | +| ------- | ----------- | -- | +| `silly` | For very detailed logs (rarely used). | - | +| `debug` | Logging of info that could be useful for developers when debugging certain issues in production. | `"payload: {>JSON<} "`

`"Reloading data X from DB"` | +| `verbose` | Logging of common events. | `"File X updated"` | +| `info` | Logging of significant / uncommon events.

_Note: If an event happens often or many times, use `verbose` instead._ | `"Initializing TSR..."`

`"Starting nightly cronjob..."`

`"Snapshot X restored"`

`"Not allowing removal of current playing segment 'xyz', making segment unsynced instead"`

`"PeripheralDevice X connected"` | +| `warn` | Used when something unexpected happened, but not necessarily due to an application bug.

These logs don't have to be acted upon directly, but could be useful to provide context to a dev/sysadmin while troubleshooting an issue. | `"PeripheralDevice X disconnected"`

`"User Error: Cannot activate Rundown (Rundown not found)" `

`"mosRoItemDelete NOT SUPPORTED"` | +| `error` | Used when something went _wrong_, preventing something from functioning.

A logged `error` should always result in a sysadmin / developer looking into the issue.

_Note: Don't use `error` for things that are out of the app's control, such as user error._ | `"Cannot read property 'length' of undefined"`

`"Failed to save Part 'X' to DB"`| +| `crit` | Fatal errors (rarely used) | - | + diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/data-model.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/data-model.md new file mode 100644 index 0000000000..8f887c92e8 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/data-model.md @@ -0,0 +1,132 @@ +--- +title: Data Model +sidebar_position: 9 +--- + +Sofie persists the majority of its data in a MongoDB database. This allows us to use Typescript friendly documents, +without needing to worry too much about the strictness of schemas, and allows us to watch for changes happening inside +the database as a way of ensuring that updates are reactive. + +Data is typically pushed to the UI or the gateways through [Publications](./publications) over the DDP connection that Meteor provides. + +## Collection Ownership + +Each collection in MongoDB is owned by a different area of Sofie. In some cases, changes are also made by another area, but we try to keep this to a minimum. +In every case, any layout changes and any scheduled cleanup are performed by the Meteor layer for simplicity. + +### Meteor + +This category of collections is rather loosely defined, as it ends up being everything that doesn't belong somewhere else + +This consists of anything that is configurable from the Sofie UI, anything needed soley for the UI and some other bits. Additionally, there are some collections which are populated by other portions of a Sofie system, such as by package manager, through an API over DDP. +Currently, there is not a very clearly defined flow for modifying these documents, with the UI often making changes directly with minimal or no validation. + +This includes: + +- [Blueprints](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/Blueprint.ts) +- [Buckets](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/Buckets.ts) +- [CoreSystem](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/CoreSystem.ts) +- [Evaluations](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/Evaluations.ts) +- [ExternalMessageQueue](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/ExternalMessageQueue.ts) +- [ExpectedPackageWorkStatuses](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/ExpectedPackageWorkStatuses.ts) +- [MediaObjects](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/MediaObjects.ts) +- [MediaWorkFlows](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/MediaWorkFlows.ts) +- [MediaWorkFlowSteps](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/MediaWorkFlowSteps.ts) +- [Organizations](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/Organization.ts) +- [PackageInfos](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/PackageInfos.ts) +- [PackageContainerPackageStatuses](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/PackageContainerPackageStatus.ts) +- [PackageContainerStatuses](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/PackageContainerStatus.ts) +- [PeripheralDeviceCommands](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/PeripheralDeviceCommand.ts) +- [PeripheralDevices](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/PeripheralDevice.ts) +- [RundownLayouts](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/RundownLayouts.ts) +- [ShowStyleBase](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/ShowStyleBase.ts) +- [ShowStyleVariant](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/ShowStyleVariant.ts) +- [Snapshots](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/Snapshots.ts) +- [Studio](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/Studio.ts) +- [TriggeredActions](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/TriggeredActions.ts) +- [TranslationsBundles](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/TranslationsBundles.ts) +- [UserActionsLog](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/UserActionsLog.ts) +- [Users](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/Users.ts) +- [Workers](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/collections/Workers.ts) +- [WorkerThreads](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/WorkerThreads.ts) + +### Ingest + +This category of collections is owned by the ingest [worker threads](./worker-threads-and-locks.md), and models a Rundown based on how it is defined by the NRCS. + +These collections are not exposed as writable in Meteor, and are only allowed to be written to by the ingest worker threads. +There is an exception to both of these; Meteor is allowed to write to it as part of migrations, and cleaning up old documents. While the playout worker is allowed to modify certain Segments that are labelled as being owned by playout. + +The collections which are owned by the ingest workers are: + +- [AdLibActions](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/AdLibActions.ts) +- [AdLibPieces](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/AdLibPieces.ts) +- [BucketAdLibActions](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/BucketAdLibActions.ts) +- [BucketAdLibPieces](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/BucketAdLibPieces.ts) +- [ExpectedMediaItems](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/ExpectedMediaItems.ts) +- [ExpectedPackages](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/ExpectedPackages.ts) +- [ExpectedPlayoutItems](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/ExpectedPlayoutItems.ts) +- [IngestDataCache](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/IngestDataCache.ts) +- [Parts](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/Parts.ts) +- [Pieces](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/Pieces.ts) +- [RundownBaselineAdLibActions](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/RundownBaselineAdLibActions.ts) +- [RundownBaselineAdLibPieces](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/RundownBaselineAdLibPieces.ts) +- [RundownBaselineObjects](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/RundownBaselineObjects.ts) +- [Rundowns](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/Rundowns.ts) +- [Segments](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/Segments.ts) + +These collections model a Rundown from the NRCS in a Sofie form. Almost all of these contain documents which are largely generated by blueprints. +Some of these collections are used by package manager to initiate work, while others form a view of the Rundown for the users, and are used as part of the model for playout. + +### Playout + +This category of collections is owned by the playout [worker threads](./worker-threads-and-locks.md), and is used to model the playout of a Rundown or set of Rundowns. + +During the final stage of an ingest operation, there is a period where the ingest worker aquires a `PlaylistLock`, so that it can ensure that the RundownPlaylist the Rundown is a part of is updated with any necessary changes following the ingest operation. During this lock, it will also attempt to [sync any ingest changes](./for-blueprint-developers/sync-ingest-changes) to the PartInstances and PieceInstances, if supported by the blueprints. + +As before, Meteor is allowed to write to these collections as part of migrations, and cleaning up old documents. + +The collections which can only be modified inside of a `PlaylistLock` are: + +- [PartInstances](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/PartInstances.ts) +- [PieceInstances](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/PieceInstances.ts) +- [RundownPlaylists](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/RundownPlaylists.ts) +- [Timelines](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/Timelines.ts) +- [TimelineDatastore](https://github.com/nrkno/sofie-core/blob/master/packages/corelib/src/dataModel/TimelineDatastore.ts) + +These collections are used in combination with many of the ingest collections, to drive playout. + +#### RundownPlaylist + +RundownPlaylists are a Sofie invention designed to solve one problem; in some NRCS it is beneficial to build a show across multiple Rundowns, which should then be concatenated for playout. +In particular, MOS has no concept of a Playlist, only Rundowns, and it was here where we need to be able to combine multiple Rundowns. + +This functionality can be used to either break down long shows into managable chunks, or to indicate a different type of show between the each portion. + +Because of this, RundownPlaylists are largely missing from the ingest side of Sofie. We do not expose them in the ingest APIs, or do anything with them throughout the majority of the blueprints generating a Rundown. +Instead, we let the blueprints specify that a Rundown should be part of a RundownPlaylist by setting the `playlistExternalId` property, where multiple Rundowns in a Studio with the same id will be grouped into a RundownPlaylist. +If this property is not used, we automatically generate a RundownPlaylist containing the Rundown by itself. + +It is during the final stages of an ingest operation, where the RundownPlaylist will be generated (with the help of blueprints), if it is necessary. +Another benefit to this approach, is that it allows for very cheaply and easily moving Rundowns between RundownPlaylists, even safely affecting a RundownPlaylist that is currently on air. + +#### Part vs PartInstance and Piece vs PieceInstance + +In the early days of Sofie, we had only Parts and Pieces, no PartInstances and PieceInstances. + +This quickly became costly and complicated to handle cases where the user used Adlibs in Sofie. Some of the challenges were: + +- When a Part is deleted from the NRCS and that part is on air, we don't want to delete it in Sofie immediately +- When a Part is modified in the NRCS and that part is on air, we may not want to apply all of the changes to playout immediately +- When a Part has finished playback and is set-as-next again, we need to make sure to discard any changes made by the previous playout, and restore it to as if was refreshly ingested (including the changes we ignored while it was on air) +- When creating an adlib part, we need to be sure that an ingest operation doesn't attempt to delete it, until playout is finished with it. +- After using an adlib in a part, we need to remove the piece it created when we set-as-next again, or reset the rundown +- When an earlier part is removed, where an infinite piece has spanned into the current part, we may not want to remove that infinite piece + +Our solution to some of this early on was to not regenerate certain Parts when receiving ingest operations for them, and to defer it until after that Part was off air. While this worked, it was not optimal to re-run ingest operations like that while doing a take. This also required the blueprint api to generate a single part in each call, which we were starting to find limiting. This was also problematic when resetting a rundown, as that would often require rerunning ingest for the whole rundown, making it a notably slow operation. + +At this point in time, Adlib Actions did not exist in Sofie. They are able to change almost every property of a Part of Piece that ingest is able to define, which makes the resetting process harder. + +PartInstances and PieceInstances were added as a way for us to make a copy of each Part and Piece, as it was selected for playout, so that we could allow ingest without risking affecting playout, and to simplify the cleanup performed. The PartInstances and PieceInstances are our record of how the Rundown was played, which we can utilise to output metadata such as for chapter markers on a web player. In earlier versions of Sofie this was tracked independently with an `AsRunLog`, which resulted in odd issues such as having `AsRunLog` entries which refered to a Part which no longer existed, or whose content was very different to how it was played. + +Later on, this separation has allowed us to more cleanly define operations as ingest or playout, and allows us to run them in parallel with more confidence that they won't accidentally wipe out each others changes. Previously, both ingest and playout operations would be modifying documents in the Piece and Part collections, making concurrent operations unsafe as they could be modifying the same Part or Piece. diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/_category_.json b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/_category_.json new file mode 100644 index 0000000000..5f6541c2b5 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Device Integrations", + "position": 5 +} \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/intro.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/intro.md new file mode 100644 index 0000000000..1604538523 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/intro.md @@ -0,0 +1,18 @@ +# Introduction + +Device integrations in Sofie are part of the Timeline State Resolver (TSR) library. A device integration has a couple of responsibilites in the Sofie eco system. First and foremost it should establish a connection with a foreign device. It should also be able to convert Sofie's idea of what the device should be doing into commands to control the device. And lastly it should export interfaces to be used by the blueprints developer. + +In order to understand all about writing TSR integrations there are some concepts to familiarise yourself with, in this documentation we will attempt to explain these. + + - [Options and mappings](./options-and-mappings.html) + - [TSR Integration API](./tsr-api.html) + - [TSR Types package](./tsr-types.html) + - [TSR Actions](./tsr-actions.html) + +But to start of we will explain the general structure of the TSR. Any user of the TSR will interface primarily with the Conductor class. Primarily the user will input device configurations, mappings and timelines into the TSR. The timeline describes the entire state of all of the devices over time. It does this by putting objects on timeline layers. Every timeline layer maps to a specific part of the device, this is configured throught the mappings. + +The timeline is converted into disctinct states at different points in time, and these states are fed to the individual integrations. As an integration developer you shouldn't have to worry about keeping track of this. It is most important that you expose \(a\) a method to convert from a Timeline State to a Device State, \(b\) a method for diffing 2 device states and (c) a way to send commands to the device. We'll dive deeper into this in [TSR Integration API](./tsr-api.html). + +:::info +The information in this section is not a conclusive guide on writing an integration, it should be use more as a guide to use while looking at a TSR integration such as the [OSC integration](https://github.com/nrkno/sofie-timeline-state-resolver/tree/master/packages/timeline-state-resolver/src/integrations/osc). +::: \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/options-and-mappings.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/options-and-mappings.md new file mode 100644 index 0000000000..1bb182f155 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/options-and-mappings.md @@ -0,0 +1,11 @@ +# Options and mappings + +For an end user to configure the system from the Sofie UI we have to expose options and mappings from the TSR. This is done through [JSON config schemas](../json-config-schema.html) in the `$schemas` folder of your integration. + +## Options + +Options are for any configuration the user needs to make for your device integration to work well. Things like IP addresses and ports go here. + +## Mappings + +A mappings is essentially an addresses into the device you are integrating with. For example, a mapping for CasparCG contains a channel and a layer. And a mapping for an Atem can be a mix effect or a downstream keyer. It is entirely possible for the user to define 2 mappings pointing to the same bit of hardware so keep that in mind while writing your integration. The granularity of the mappings influences both how you write your device as well as the shape of the timeline objects. If, for example, we had not included the layer number in the CasparCG mapping, we would have had to define this separately on every timeline object. \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-actions.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-actions.md new file mode 100644 index 0000000000..791c6f5a26 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-actions.md @@ -0,0 +1,11 @@ +# TSR Actions + +Sometimes a state based model isn't enough and you just need to fire an action. In Sofie we try to be strict about any playout operations needing to be state based, i.e. doing a transition operation on a vision mixer should be a result of a state change, not an action. However, there are things that are easier done with actions. For example cleaning up a playlist on a graphics server or formatting a disk on a recorder. For these scenarios we have added TSR Actions. + +TSR Actions can be triggered through the UI by a user, through blueprints when the rundown is activated or deactivated or through adlib actions. + +When implementing the TSR Actions API you should start by defining a JSON schema outlying the action id's and payload your integration will consume. Once you've done this you're ready to implement the actions as callbacks on the `actions` property of your integration. + +:::warning +Beware that if your action changes the state of the device you should handle this appropriately by resetting the resolver +::: diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-api.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-api.md new file mode 100644 index 0000000000..e68424455e --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-api.md @@ -0,0 +1,28 @@ +# TSR Integration API + +:::info +As of version 1.50, there still exists a legacy API for device integrations. In this documentation we will only consider the more modern variant informally known as the _StateHandler_ format. +::: + +## Setup and status + +There are essentially 2 parts to the TSR API, the first thing you need to do is set up a connection with the device you are integrating with. This is done in the `init` method. It takes a parameter with the Device options as specified in the config schema. Additionally a `terminate` call is to be implemented to tear down the connection and prepare any timers to be garbage collected. + +Regarding status there are 2 important methods to be implemented, one is a getter for the `connected` status of the integration and the other is `getStatus` which should inform a TSR user of the status of device. You can add messages in this status as well. + +## State and commands + +The second part is where the bulk of the work happens. First your implementation for `convertTimelineStateToDeviceState` will be called with a Timeline State and the mappings for your integration. You are ought to return a "Device State" here which is an object representing the state of your device as inferred from the Timeline State and mappings. Then the next implementation is of the `diffStates` method, which will be called with 2 Device States as you've generated them earlier. The purpose of this method is to generate commands such that a state change from Device State A to Device State B can be executed. Hence it is called a "diff". The last important method here is `sendCommand` which will be called with the commands you've generated earlier when the TSR wants to transitition from State A to State B. + +Another thing to implement is the `actions` property. You can leave it as an empty object initially or read more about it in [TSR Actions](./tsr-actions.md). + +## Logging and emitting events + +Logging is done through an event emitter as is described in the DeviceEvents interface. You should also emit an event any time the connection status should change. There is an event you can emit to rerun the resolving process in TSR as well, this will more or less create new Timeline States from the timeline, diff them and see if they should be executed. + +## Best practices + + - The `init` method is asynchronous but you should not use it to wait for timeouts in your connection to reject it. Instead the rest of your integration should gracefully deal with a (initially) disconnected device. + - The result of the `getStatus` method is displayed in the UI of Sofie so try to put helpful information in the messages and only elevate to a "bad" status if something is really wrong, like being fully disconnected from a device. + - Be aware for side effects in your implementations of `convertTimelineStateToDeviceState` and `diffStates` they are _not_ guaranteed to be chronological and the states changes may never actually be executed. + - If you need to do any time aware commands (such as seeking in a media file) use the time from the Timeline State to do your calculations for these \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-types.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-types.md new file mode 100644 index 0000000000..0c9d2e5108 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/device-integrations/tsr-types.md @@ -0,0 +1,7 @@ +# TSR Types + +The TSR monorepo contains a types package called `timeline-state-resolver-types`. The intent behind this package is that you may want to generate a Timeline in a place where you don't want to import the TSR library for performance reasons. Blueprints are a good example of this since the webpack setup does not deal well with importing everything. + +## What you should know about this + +When the TSR is built the types for the Mappings, Options and Actions for your integration will be auto generated under `src/generated`. In addition to this you should describe the content property of the timeline objects in a file using interfaces. If you're adding a new integration also add it to the `DeviceType` enum as described in `index.ts`. diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/_category_.json b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/_category_.json new file mode 100644 index 0000000000..c4c3c8c242 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "For Blueprint Developers", + "position": 4 +} \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/_part-timings-demo.jsx b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/_part-timings-demo.jsx new file mode 100644 index 0000000000..98cb9f4275 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/_part-timings-demo.jsx @@ -0,0 +1,173 @@ +import React, { useState } from 'react' + +/** + * This is a demo showing the interactions between the part and piece groups on the timeline. + * The maths should be the same as in `meteor/lib/rundown/timings.ts`, but in a simplified form + */ + +const MS_TO_PIXEL_CONSTANT = 0.1 + +const viewPortStyle = { + width: '100%', + backgroundSize: '40px 40px', + backgroundImage: + 'linear-gradient(to right, grey 1px, transparent 1px), linear-gradient(to bottom, grey 1px, transparent 1px)', + overflowX: 'hidden', + display: 'flex', + flexDirection: 'column', + position: 'relative', +} + +export function PartTimingsDemo() { + const [postrollA1, setPostrollA1] = useState(0) + const [postrollA2, setPostrollA2] = useState(0) + const [prerollB1, setPrerollB1] = useState(0) + const [prerollB2, setPrerollB2] = useState(0) + const [outTransitionDuration, setOutTransitionDuration] = useState(0) + const [inTransitionBlockDuration, setInTransitionBlockDuration] = useState(0) + const [inTransitionContentsDelay, setInTransitionContentsDelay] = useState(0) + const [inTransitionKeepaliveDuration, setInTransitionKeepaliveDuration] = useState(0) + + // Arbitrary point in time for the take to be based around + const takeTime = 2400 + + const outTransitionTime = outTransitionDuration - inTransitionKeepaliveDuration + + // The amount of time needed to preroll Part B before the 'take' point + const partBPreroll = Math.max(prerollB1, prerollB2) + const prerollTime = partBPreroll - inTransitionContentsDelay + + // The amount to delay the part 'switch' to, to ensure the outTransition has time to complete as well as any prerolls for part B + const takeOffset = Math.max(0, outTransitionTime, prerollTime) + const takeDelayed = takeTime + takeOffset + + // Calculate the part A objects + const pieceA1 = { time: 0, duration: takeDelayed + inTransitionKeepaliveDuration + postrollA1 } + const pieceA2 = { time: 0, duration: takeDelayed + inTransitionKeepaliveDuration + postrollA2 } + const partA = { time: 0, duration: Math.max(pieceA1.duration, pieceA2.duration) } // part stretches to contain the piece + + // Calculate the transition objects + const pieceOutTransition = { + time: partA.time + partA.duration - outTransitionDuration - Math.max(postrollA1, postrollA2), + duration: outTransitionDuration, + } + const pieceInTransition = { time: takeDelayed, duration: inTransitionBlockDuration } + + // Calculate the part B objects + const partBBaseDuration = 2600 + const partB = { time: takeTime, duration: partBBaseDuration + takeOffset } + const pieceB1 = { time: takeDelayed + inTransitionContentsDelay - prerollB1, duration: partBBaseDuration + prerollB1 } + const pieceB2 = { time: takeDelayed + inTransitionContentsDelay - prerollB2, duration: partBBaseDuration + prerollB2 } + const pieceB3 = { time: takeDelayed + inTransitionContentsDelay + 300, duration: 200 } + + return ( +
+
+ + + + + + + + + + + + + + + +
+ + {/* Controls */} + + + + + + + + + +
+
+ ) +} + +function TimelineGroup({ duration, time, name, color }) { + return ( +
+ {name} +
+ ) +} + +function TimelineMarker({ time, title }) { + return ( +
+   +
+ ) +} + +function InputRow({ label, max, value, setValue }) { + return ( + + {label} + + setValue(parseInt(e.currentTarget.value))} + /> + + + ) +} diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/ab-playback.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/ab-playback.md new file mode 100644 index 0000000000..1a78316f77 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/ab-playback.md @@ -0,0 +1,236 @@ +# AB Playback + +:::info +Prior to 1.50 of Sofie, this was implemented in Blueprints and not natively in Sofie-core +::: + +_AB Playback_ is a common technique for clip playback. The aim is to be able to play multiple clips back to back, alternating which player is used for each clip. +At first glance it sounds simple to handle, but it quickly becomes complicated when we consider the need to allow users to run adlibs and that the system needs to seamlessly update pre-programmed clips when this happens. + +To avoid this problem, we take an approach of labelling pieces as needing an AB assignment and leaving timeline objects to have some unresolved values during the ingest blueprint operations, and we perform the AB resolving when building the timeline for playout. + +There are other challenges to the resolving to think about too, which make this a challenging area to tackle, and not something that wants to be considered when starting out with blueprints. Some of these challenges are: + +- Users get confused if the player of a clip changes without a reason +- Reloading an already loaded clip can be costly, so should be avoided when possible +- Adlibbing a clip, or changing what Part is nexted can result in needing to move what player a clip has assigned +- Postroll or preroll is often needed +- Some studios can have less players available than ideal. (eg, going back to back between two clips, and a clip is playing on the studio monitor) + +## Defining Piece sessions + +An AB-session is a request for an AB player for the lifetime of the object or Piece. The resolver operates on these sessions, to identify when players are needed and to identify which objects and Pieces are linked and should use the same Player. + +In order for the AB resolver to know what AB sessions there are on the timeline, and how they all relate to each other, we define `abSessions` properties on various objects when defining Pieces and their content during the `getSegment` blueprint method. + +The AB resolving operates by looking at all the Pieces on the timeline, and plotting all the requested abSessions out in time. It will then iterate through each of these sessions in time order and assign them in order to the available players. +Note: The sessions of TimelineObjects are not considered at this point, except for those in lookahead. + +Both Pieces and TimelineObjects accept an array of AB sessions, and are capable of using multiple AB pools on the same object. Eg, choosing a clip player and the DVE to play it through. + +:::warning +The sessions of TimelineObjects are not considered during the resolver stage, except for lookahead objects. +If a TimelineObject has an `abSession` set, its parent Piece must declare the same session. +::: + +For example: + +```ts +const partExternalId = 'id-from-nrcs' +const piece: Piece = { + externalId: partExternalId, + name: 'My Piece', + + abSessions: [{ + sessionName: partExternalId, + poolName: 'clip' + }], + + ... +} +``` + +This declares that this Piece requires a player from the 'clip' pool, with a unique sessionName. + +:::info +The `sessionName` property is an identifier for a session within the Segment. +Any other Pieces or TimelineObjects that want to share the session should use the same sessionName. Unrelated sessions must use a different name. +::: + +## Enabling AB playback resolving + +To enable AB playback for your blueprints, the `getAbResolverConfiguration` method of a ShowStyle blueprint must be implemented. This informs Sofie that you want the AB playback logic to run, and configures the behaviour. + +A minimal implementation of this is: + +```ts +getAbResolverConfiguration: (context: IShowStyleContext): ABResolverConfiguration => { + return { + resolverOptions: { + idealGapBefore: 1000, + nowWindow: 2000, + }, + pools: { + clip: [1, 2], + }, + } +} +``` + +The `resolverOptions` property defines various configuration that will affect how sessions are assigned to players. +The `pools` property defines the AB pools in your system, along with the ids of the players in the pools. These do not have to be sequential starting from 1, and can be any numbers you wish. The order used here will define the order the resolver will assign to. + +## Updating the timeline from the assignments + +There are 3 possible strategies for applying the assignments to timeline objects. The applying and ab-resolving is done just before `onTimelineGenerate` from your blueprints is called. + +### TimelineObject Keyframes + +The simplest approach is to use timeline keyframes, which can be labelled as belong to an abSession. These keyframes must be generated during ingest. + +This strategy works best for changing inputs on a video-mixer or other scenarios where a property inside of a timeline object needs changing. + +```ts +let obj = { + id: '', + enable: { start: 0 }, + layer: 'atem_me_program', + content: { + deviceType: TSR.DeviceType.ATEM, + type: TSR.TimelineContentTypeAtem.ME, + me: { + input: 0, // placeholder + transition: TSR.AtemTransitionStyle.CUT, + }, + }, + keyframes: [ + { + id: `mp_1`, + enable: { while: '1' }, + disabled: true, + content: { + input: 10, + }, + preserveForLookahead: true, + abSession: { + pool: 'clip', + index: 1, + }, + }, + { + id: `mp_2`, + enable: { while: '1' }, + disabled: true, + content: { + input: 11, + }, + preserveForLookahead: true, + abSession: { + pool: 'clip', + index: 2, + }, + }, + ], + abSessions: [ + { + pool: 'clip', + name: 'abcdef', + }, + ], +} +``` + +This object demonstrates how keyframes can be used to perform changes based on an assigned ab player session. The object itself must be labelled with the `abSession`, in the same way as the Piece is. +Each keyframe can be labelled with an `abSession`, with only one from the pool being left active. If `disabled` is set on the keyframe, that will be unset, and the other keyframes for the pool will be removed. + +Setting `disabled: true` is not strictly necessary, but ensures that the keyframe will be inactive in case that ab-pool is not processed. +In this example we are setting `preserveForLookahead` so that the keyframes are present on lookahead objects. If not set, then the keyframes will be removed by lookahead. + +### TimelineObject layer changing + +Another apoproach is to move objects between timeline layers. For example, player 1 is on CasparCG channel 1, with player 2 on CasparCG channel 2. This requires a different mapping for each layer. + +This strategy works best for playing a clip, where the whole object needs to move to different mappings. + +To enable this, the `ABResolverConfiguration` object returned from `getAbResolverConfiguration` can have a set of rules defined with the `timelineObjectLayerChangeRules` property. + +For example: + +```ts +getAbResolverConfiguration: (context: IShowStyleContext): ABResolverConfiguration => { + return { + resolverOptions: { + idealGapBefore: 1000, + nowWindow: 2000, + }, + pools: { + clip: [1, 2], + }, + timelineObjectLayerChangeRules: { + ['casparcg_player_clip_pending']: { + acceptedPoolNames: [AbSessionPool.CLIP], + newLayerName: (playerId: number) => `casparcg_player_clip_${playerId}`, + allowsLookahead: true, + }, + }, + } +} +``` + +And a timeline object: + +```ts +const clipObject: TimelineObjectCoreExt<> = { + id: '', + enable: { start: 0 }, + layer: 'casparcg_player_clip_pending', + content: { + deviceType: TSR.DeviceType.CASPARCG, + type: TSR.TimelineContentTypeCasparCg.MEDIA, + file: 'AMB', + }, + abSessions: [ + { + pool: 'clip', + name: 'abcdef', + }, + ], +} +``` + +This will result in the timeline object being moved to `casparcg_player_clip_1` if the clip is assigned to player 1, or `casparcg_player_clip_2` if the clip is assigned to player 2. + +This is also compatible with lookahead. To do this, the `casparcg_player_clip_pending` mapping should be created with the lookahead configuration set there, this should be of type `ABSTRACT`. The AB resolver will detect this lookahead object and it will get an assignment when a player is available. Lookahead should not be enabled for the `casparcg_player_clip_1` and other final mappings, as lookahead is run before AB so it will not find any objects on those layers. + +### Custom behaviour + +Sometimes, something more complex is needed than what the other options allow for. To support this, the `ABResolverConfiguration` object has an optional property `customApplyToObject`. It is advised to use the other two approaches when possible. + +```ts +getAbResolverConfiguration: (context: IShowStyleContext): ABResolverConfiguration => { + return { + resolverOptions: { + idealGapBefore: 1000, + nowWindow: 2000, + }, + pools: { + clip: [1, 2], + }, + customApplyToObject: ( + context: ICommonContext, + poolName: string, + playerId: number, + timelineObject: OnGenerateTimelineObj + ) => { + // Your own logic here + + return false + }, + } +} +``` + +Inside this function you are able to make any changes you like to the timeline object. +Return true if the object was changed, or false if it is unchanged. This allows for logging whether Sofie failed to modify an object for an ab assignment. + +For example, we use this to remap audio channels deep inside of some Sisyfos timeline objects. It is not possible for us to do this with keyframes due to the keyframes being applied with a shallow merge for the Sisyfos TSR device. diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/hold.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/hold.md new file mode 100644 index 0000000000..35d8dde7e4 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/hold.md @@ -0,0 +1,52 @@ +# Hold + +_Hold_ is a feature in Sofie to allow for a special form of take between two parts. It allows for the new part to start with some portions of the old part being retained, with the next 'take' stopping the remaining portions of the old part and not performing a true take. + +For example, it could be setup to hold back the video when going between two clips, creating what is known in film editing as a [split edit](https://en.wikipedia.org/wiki/Split_edit) or [J-cut](https://en.wikipedia.org/wiki/J_cut). The first _Take_ would start the audio from an _A-Roll_ (second clip), but keep the video playing from a _B-Roll_ (first clip). The second _Take_ would stop the first clip entirely, and join the audio and video for the second clip. + +![A timeline of a J-Cut in a Non-Linear Video Editor](/img/docs/video_edit_hold_j-cut.png) + +## Flow + +While _Hold_ is active or in progress, an indicator is shown in the header of the UI. +![_Hold_ in Rundown View header](/img/docs/rundown-header-hold.png) + +It is not possible to run any adlibs while a hold is active, or to change the nexted part. Once it is in progress, it is not possible to abort or cancel the _Hold_ and it must be run to completion. If the second part has an autonext and that gets reached before the _Hold_ is completed, the _Hold_ will be treated as completed and the autonext will execute as normal. + +When the part to be held is playing, with the correct part as next, the flow for the users is: + +- Before + - Part A is playing + - Part B is nexted +- Activate _Hold_ (By hotkey or other user action) + - Part A is playing + - Part B is nexted +- Perform a take into the _Hold_ + - Part B is playing + - Portions of Part A remain playing +- Perform a take to complete the _Hold_ + - Part B is playing + +Before the take into the _Hold_, it can be cancelled in the same way it was activated. + +## Supporting Hold in blueprints + +:::note +The functionality here is a bit limited, as it was originally written for one particular use-case and has not been expanded to support more complex scenarios. +Some unanswered questions we have are: + +- Should _Hold_ be rewritten to be done with adlib-actions instead to allow for more complex scenarios? +- Should there be a way to more intelligently check if _Hold_ can be done between two Parts? (perhaps a new blueprint method?) +::: + +The blueprints have to label parts as supporting _Hold_. +You can do this with the [`holdMode`](https://nrkno.github.io/sofie-core/typedoc/interfaces/_sofie_automation_blueprints_integration.IBlueprintPart.html#holdMode) property, and labelling it possible to _Hold_ from or to the part. + +Note: If the user manipulates what part is set as next, they will be able to do a _Hold_ between parts that are not sequential in the Rundown. + +You also have to label Pieces as something to extend into the _Hold_. Not every piece will be wanted, so it is opt-in. +You can do this with the [`extendOnHold`](https://nrkno.github.io/sofie-core/typedoc/interfaces/_sofie_automation_blueprints_integration.IBlueprintPiece.html#extendOnHold) property. The pieces will get extended in the same way as infinite pieces, but limited to only be extended into the one part. The usual piece collision and priority logic applies. + +Finally, you may find that there are some timeline objects that you don't want to use inside of the extended pieces, or there are some objects in the part that you don't want active while the _Hold_ is. +You can mark an object with the [`holdMode`](https://nrkno.github.io/sofie-core/typedoc/interfaces/_sofie_automation_blueprints_integration.TimelineObjectCoreExt.html#holdMode) property to specify its presence during a _Hold_. +The `HoldMode.ONLY` mode tells the object to only be used when in a _Hold_, which allows for doing some overrides in more complex scenarios. diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/intro.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/intro.md new file mode 100644 index 0000000000..ba84522629 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/intro.md @@ -0,0 +1,20 @@ +--- +sidebar_position: 1 +--- + +# Introduction + +:::caution +Documentation for this page is yet to be written. +::: + +[Blueprints](../../user-guide/concepts-and-architecture.md#blueprints) are programs that run inside Sofie Core and interpret +data coming in from the Rundowns and transform that into playable elements. They use an API published in [@sofie-automation/blueprints-integration](https://nrkno.github.io/sofie-core/typedoc/modules/_sofie_automation_blueprints_integration.html) library to expose their functionality and communicate with Sofie Core. + +Technically, a Blueprint is a JavaScript object, implementing one of the `BlueprintManifestBase` interfaces. + +Currently, there are three types of Blueprints: + +- [Show Style Blueprints](https://nrkno.github.io/sofie-core/typedoc/interfaces/_sofie_automation_blueprints_integration.ShowStyleBlueprintManifest.html) - handling converting NRCS Rundown data into Sofie Rundowns and content. +- [Studio Blueprints](https://nrkno.github.io/sofie-core/typedoc/interfaces/_sofie_automation_blueprints_integration.StudioBlueprintManifest.html) - handling selecting ShowStyles for a given NRCS Rundown and assigning NRCS Rundowns to Sofie Playlists +- [System Blueprints](https://nrkno.github.io/sofie-core/typedoc/interfaces/_sofie_automation_blueprints_integration.SystemBlueprintManifest.html) - handling system provisioning and global configuration diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/lookahead.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/lookahead.md new file mode 100644 index 0000000000..7c2d644969 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/lookahead.md @@ -0,0 +1,96 @@ +# Lookahead + +Lookahead allows Sofie to look into future Parts and Pieces, in order to preload or preview what is coming up. The aim is to fill in the gaps between your TimelineObjects with lookahead versions of these objects. +In this way, it can be used to provide functionality such as an AUX on your vision mixer showing the next cut, or to load the next clip into the media player. + +## Defining + +Lookahead can be enabled by configuring a few properties on a mapping: + +```ts +/** What method core should use to create lookahead objects for this layer */ +lookahead: LookaheadMode +/** The minimum number lookahead objects to create from future parts for this layer. Default = 1 */ +lookaheadDepth?: number +/** Maximum distance to search for lookahead. Default = undefined */ +lookaheadMaxSearchDistance?: number +``` + +With `LookaheadMode` defined as: + +```ts +export enum LookaheadMode { + /** + * Disable lookahead for this layer + */ + NONE = 0, + /** + * Preload content with a secondary layer. + * This requires support from the TSR device, to allow for preloading on a resource at the same time as it being on air. + * For example, this allows for your TimelineObjects to control the foreground of a CasparCG layer, with lookahead controlling the background of the same layer. + */ + PRELOAD = 1, + /** + * Fill the gaps between the planned objects on a layer. + * This is the primary lookahead mode, and appears to TSR devices as a single layer of simple objects. + */ + WHEN_CLEAR = 3, +} +``` + +If undefined, `lookaheadMaxSearchDistance` currently has a default distance of 10 parts. This number was chosen arbitrarily, and could change in the future. Be careful when choosing a distance to not set it too high. All the Pieces from the parts being searched have to be loaded from the database, which can come at a noticable cost. + +If you are doing [AB Playback](./ab-playback.md), or performing some other processing of the timeline in `onTimelineGenerate`, you may benefit from increasing the value of `lookaheadDepth`. In the case of AB Playback, you will likely want to set it to the number of players available in your pool. + +Typically, TimelineObjects do not need anything special to support lookahead, other than a sensible `priority` value. Lookahead objects are given a priority between `0` and `0.1`. Generally, your baseline objects should have a priority of `0` so that they are overridden by lookahead, and any objects from your Parts and Pieces should have a priority of `1` or higher, so that they override lookahead objects. + +If there are any keyframes on TimelineObjects that should be preserved when being converted to a lookahead object, they will need the `preserveForLookahead` property set. + +## How it works + +Lookahead is calculated while the timeline is being built, and searches based on the playhead, rather than looking at the planned Parts. + +The searching operates per-layer first looking at the current PartInstance, then the next PartInstance and then any Parts after the next PartInstance in the rundown. Any Parts marked as `invalid` or `floated` are ignored. This is what allows lookahead to be dynamic based on what the User is doing and intending to play. + +It is searching Parts in that order, until it has either searched through the `lookaheadMaxSearchDistance` number of Parts, or has found at least `lookaheadDepth` future timeline objects. + +Any pieces marked as `pieceType: IBlueprintPieceType.InTransition` will be considered only if playout intends to use the transition. +If an object is found in both a normal piece with `{ start: 0 }` and in an InTransition piece, then the objects from the normal piece will be ignored. + +These objects are then processed and added to the timeline. This is done in one of two ways: + +1. As timed objects. + If the object selected for lookahead is already on the timeline (it is in the current part, or the next part and autonext is enabled), then timed lookahead objects are generated. These objects are to fill in the gaps, and get their `enable` object to reference the objects on the timeline that they are filling between. + The `lookaheadDepth` setting of the mapping is ignored for these objects. + +2. As future objects. + If the object selected for lookahead is not on the timeline, then simpler objects are generated. Instead, these get an enable of either `{ while: '1' }`, or set to start after the last timed object on that layer. This lets them fill all the time after any other known objects. + The `lookaheadDepth` setting of the mapping is respected for these objects, with this number defining the **minimum** number future objects that will be produced. These future objects are inserted with a decreasing `priority`, starting from 0.1 decreasing down to but never reaching 0. + When using the `WHEN_CLEAR` lookahead mode, all but the first will be set as `disabled`, to ensure they aren't considered for being played out. These `disabled` objects can be used by `onTimelineGenerate`, or they will be dropped from the timeline if left `disabled`. + When there are multiple future objects on a layer, only the first is useful for playout directly, but the others are often utilised for [AB Playback](./ab-playback.md) + +Some additional changes done when processing each lookahead timeline object: + +- The `id` is processed to be unique +- The `isLookahead` property is set as true +- If the object has any keyframes, any not marked with `preserveForLookahead` are removed +- The object is removed from any group it was contained within +- If the lookahead mode used is `PRELOAD`, then the layer property is changed, with the `lookaheadForLayer` property set to indicate the layer it is for. + +The resulting objects are appended to the timeline and included in the call to `onTimelineGenerate` and the [AB Playback](./ab-playback.md) resolving. + +## Advanced Scenarios + +Because the lookahead objects are included in the timeline to `onTimelineGenerate`, this gives you the ability to make changes to the lookahead output. + +[AB Playback](./ab-playback.md) started out as being implemented inside of `onTimelineGenerate` and relies on lookahead objects being produced before reassigning them to other mappings. + +If any objects found by lookahead have a class `_lookahead_start_delay`, they will be given a short delay in their start time. This is a hack introduced to workaround a timing issue. At some point this will be removed once a proper solution is found. + +Sometimes it can be useful to have keyframes which are only applied when in lookahead. That can be achieved by setting `preserveForLookahead`, making the keyframe be disabled, and then re-enabling it inside `onTimelineGenerate` at the correct time. + +It is possible to implement a 'next' AUX on your vision mixer by: + +- Setup this mapping with `lookaheadDepth: 1` and `lookahead: LookaheadMode.WHEN_CLEAR` +- Each Part creates a TimelineObject on this mapping. Crucially, these have a priority of 0. +- Lookahead will run and will insert its objects overriding your predefined ones (because of its higher priority). Resulting in the AUX always showing the lookahead object. diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/part-and-piece-timings.mdx b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/part-and-piece-timings.mdx new file mode 100644 index 0000000000..2b21205a3c --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/part-and-piece-timings.mdx @@ -0,0 +1,141 @@ +import { PartTimingsDemo } from './_part-timings-demo' + +# Part and Piece Timings + +Parts and pieces are the core groups that form the timeline, and define start and end caps for the other timeline objects. + +When referring to the timeline in this page, we mean the built timeline objects that is sent to playout-gateway. +It is made of the previous PartInstance, the current PartInstance and sometimes the next PartInstance. + +### The properties + +These are stripped down interfaces, containing only the properties that are relevant for the timeline generation: + +```ts +export interface IBlueprintPart { + /** Should this item should progress to the next automatically */ + autoNext?: boolean + /** How much to overlap on when doing autonext */ + autoNextOverlap?: number + + /** Timings for the inTransition, when supported and allowed */ + inTransition?: IBlueprintPartInTransition + + /** Should we block the inTransition when starting the next Part */ + disableNextInTransition?: boolean + + /** Timings for the outTransition, when supported and allowed */ + outTransition?: IBlueprintPartOutTransition + + /** Expected duration of the line, in milliseconds */ + expectedDuration?: number +} + +/** Timings for the inTransition, when supported and allowed */ +export interface IBlueprintPartInTransition { + /** Duration this transition block a take for. After this time, another take is allowed which may cut this transition off early */ + blockTakeDuration: number + /** Duration the previous part be kept playing once the transition is started. Typically the duration of it remaining in-vision */ + previousPartKeepaliveDuration: number + /** Duration the pieces of the part should be delayed for once the transition starts. Typically the duration until the new part is in-vision */ + partContentDelayDuration: number +} + +/** Timings for the outTransition, when supported and allowed */ +export interface IBlueprintPartOutTransition { + /** How long to keep this part alive after taken out */ + duration: number +} + +export interface IBlueprintPiece { + /** Timeline enabler. When the piece should be active on the timeline. */ + enable: { + start: number | 'now' // 'now' is only valid from adlib-actions when inserting into the current part + duration?: number + } + + /** Whether this piece is a special piece */ + pieceType: IBlueprintPieceType + + /// from IBlueprintPieceGeneric: + + /** Whether and how the piece is infinite */ + lifespan: PieceLifespan + + /** + * How long this piece needs to prepare its content before it will have an effect on the output. + * This allows for flows such as starting a clip playing, then cutting to it after some ms once the player is outputting frames. + */ + prerollDuration?: number +} + +/** Special types of pieces. Some are not always used in all circumstances */ +export enum IBlueprintPieceType { + Normal = 'normal', + InTransition = 'in-transition', + OutTransition = 'out-transition', +} +``` + +### Concepts + +#### Piece Preroll + +Often, a Piece will need some time to do some preparation steps on a device before it should be considered as active. A common example is playing a video, as it often takes the player a couple of frames before the first frame is output to SDI. +This can be done with the `prerollDuration` property on the Piece. A general rule to follow is that it should not have any visible or audible effect on the output until `prerollDuration` has elapsed into the piece. + +When the timeline is built, the Pieces get their start times adjusted to allow for every Piece in the part to have its preroll time. If you look at the auto-generated pieceGroup timeline objects, their times will rarely match the times specified by the blueprints. Additionally, the previous Part will overlap into the Part long enough for the preroll to complete. + +Try the interactive to see how the prerollDuration properties interact. + +#### In Transition + +The in transition is a special Piece that can be played when taking into a Part. It is represented as a Piece, partly to show the user the transition type and duration, and partly to allow for timeline changes to be applied when the timeline generation thinks appropriate. + +When the `inTransition` is set on a Part, it will be applied when taking into that Part. During this time, any Pieces with `pieceType: IBlueprintPieceType.InTransition` will be added to the timeline, and the `IBlueprintPieceType.Normal` Pieces in the Part will be delayed based on the numbers from `inTransition` + +Try the interactive to see how the an inTransition affects the Piece and Part layout. + +#### Out Transition + +The out transition is a special Piece that gets played when taking out of the Part. It is intended to allow for some 'visual cleanup' before the take occurs. + +In effect, when `outTransition` is set on a Part, the take out of the Part will be delayed by the duration defined. During this time, any pieces with `pieceType: IBlueprintPieceType.OutTransition` will be added to the timeline and will run until the end of the Part. + +Try the interactive to see how this affects the Parts. + +### Piece postroll + +Sometimes rather than extending all the pieces and playing an out transition piece on top we want all pieces to stop except for 1, this has the same goal of 'visual cleanup' as the out transition but works slightly different. The main concept is that an out transition delays the take slightly but with postroll the take executes normally however the pieces with postroll will keep playing for a bit after the take. + +When the `postrollDuration` is set on a piece the part group will be extended slightly allowing pieces to play a little longer, however any piece that do not have postroll will end at their regular time. + +#### Autonext + +Autonext is a way for a Part to be made a fixed length. After playing for its `expectedDuration`, core will automatically perform a take into the next part. This is commonly used for fullscreen videos, to exit back to a camera before the video freezes on the last frame. It is enabled by setting the `autoNext: true` on a Part, and requires `expectedDuration` to be set to a duration higher than `1000`. + +In other situations, it can be desirable for a Part to overlap the next one for a few seconds. This is common for Parts such as a title sequence or bumpers, where the sequence ends with an keyer effect which should reveal the next Part. +To achieve this you can set `autoNextOverlap: 1000 // ms` to make the parts overlap on the timeline. In doing so, the in transition for the next Part will be ignored. + +The `autoNextOverlap` property can be thought of an override for the intransition on the next part defined as: + +```ts +const inTransition = { + blockTakeDuration: 1000, + partContentDelayDuration: 0, + previousPartKeepaliveDuration: 1000, +} +``` + +#### Infinites + +Pieces with an infinite lifespan (ie, not `lifespan: PieceLifespan.WithinPart`) get handled differently to other pieces. + +Only one pieceGoup is created for an infinite Piece which is present in multiple of the current, next and previous Parts. +The Piece calculates and tracks its own started playback times, which is preserved and reused in future takes. On the timeline it lives outside of the partGroups, but still gets the same caps applied when appropriate. + +### Interactive timings demo + +Use the sliders below to see how various Preroll and In & Out Transition timing properties interact with each other. + + diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/sync-ingest-changes.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/sync-ingest-changes.md new file mode 100644 index 0000000000..0d34a7c935 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/sync-ingest-changes.md @@ -0,0 +1,23 @@ +--- +title: Sync Ingest Changes +--- + +Since PartInstances and PieceInstances were added to Sofie, the default behaviour in Sofie is to not propogate any ingest changes from a Part onto its PartInstances. + +This is a safety net as without a detailed understanding of the Part and the change, we can't know whether it is safe to make on air. Without this, it would be possible for the user to change a clip name in the NRCS, and for Sofie to happily propogate that could result in a sudden change of clip mid sentence, or black if the clip needed to be copied to the playout server. This gets even more complicated when we consider that an adlib-action could have already modified a PartInstance, with changes that should likely not be overwritten with the newly ingested Part. + +Instead, this propogation can be implemented by a ShowStyle blueprint in the `syncIngestUpdateToPartInstance` method, in this way the implementation can be tailored to understand the change and its potential impact. This method is able to update the previous, current and next PartInstances. Any PartInstances older than the previous is no longer being used on the timeline so is now simply a record of how it was played and updating it would have no benefit. Sofie never has any further than the next PartInstance generated, so for any Part after that the Part is all that exists for it, so any changes will be used when it becomes the next. + +In this blueprint method, you are able to update almost any of the properties that are available to you both during ingest, and during adlib actions. It is possible the leave the Part in a broken state after this, so care must be taken to ensure it is not. If the call to your method throws an uncaught error, the changes you have made so far will be discarded but the rest of the ingest operation will continue as normal. + +### Tips + +- You should make use of the `metaData` fields on each Part and Piece to help work out what has changed. At NRK, we store the parsed ingest data (after converting the MOS to an intermediary json format) for the Part here, so that we can do a detailed diff to figure out whether a change is safe to accept. + +- You should track in `metaData` whether a part has been modified by an adlib-action in a way that makes this sync unsafe. + +- At NRK, we differentiate the Pieces into `primary`, `secondary`, `adlib`. This allows us to control the updates more granularly. + +- `newData.part` will be `undefined` when the PartInstance is orphaned. Generally, it's useful to differentiate the behavior of the implementation of this function based on `existingPartInstance.partInstance.orphaned` state + +- `playStatus: previous` means that the currentPartInstance is `orphaned: adlib-part` and thus possibly depends on an already past PartInstance for some of it's properties. Therefore the blueprint is allowed to modify the most recently played non-adlibbed PartInstance using ingested data. diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/timeline-datastore.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/timeline-datastore.md new file mode 100644 index 0000000000..e739ee0add --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/for-blueprint-developers/timeline-datastore.md @@ -0,0 +1,85 @@ +# Timeline Datastore + +The timeline datastore is a key-value store that can be used in conjuction with the timeline. The benefit of modifying values in the datastore is that the timings in the timeline are not modified so we can skip a lot of complicated calculations which reduces the system response time. An example usecase of the datastore feature is a fastpath for cutting cameras. + +## API + +In order to use the timeline datastore feature 2 API's are to be used. The timeline object has to contain a reference to a key in the datastore and the blueprints have to add a value for that key to the datastore. These references are added on the content field. + +### Timeline API + +```ts +/** + * An object containing references to the datastore + */ +export interface TimelineDatastoreReferences { + /** + * localPath is the path to the property in the content object to override + */ + [localPath: string]: { + /** Reference to the Datastore key where to fetch the value */ + datastoreKey: string + /** + * If true, the referenced value in the Datastore is only applied after the timeline-object has started (ie a later-started timeline-object will not be affected) + */ + overwrite: boolean + } +} +``` + +### Timeline API example + +```ts +const tlObj = { + id: 'obj0', + enable: { start: 1000 }, + layer: 'layer0', + content: { + deviceType: DeviceType.Atem, + type: TimelineObjectAtem.MixEffect, + + $references: { + 'me.input': { + datastoreKey: 'camInput', + overwrite: true, + }, + }, + + me: { + input: 1, + transition: TransitionType.Cut, + }, + }, +} +``` + +### Blueprints API + +Values can be added and removed from the datastore through the adlib actions API. + +```ts +interface DatastoreActionExecutionContext { + setTimelineDatastoreValue(key: string, value: unknown, mode: DatastorePersistenceMode): Promise + removeTimelineDatastoreValue(key: string): Promise +} + +enum DatastorePersistenceMode { + Temporary = 'temporary', + indefinite = 'indefinite', +} +``` + +The data persistence mode work as follows: + +- Temporary: this key-value pair may be cleaned up if it is no longer referenced to from the timeline, in practice this will currently only happen during deactivation of a rundown +- This key-value pair may _not_ be automatically removed (it can still be removed by the blueprints) + +The above context methods may be used from the usual adlib actions context but there is also a special path where none of the usual cached data is available, as loading the caches may take some time. The `executeDataStoreAction` method is executed just before the `executeAction` method. + +## Example use case: camera cutting fast path + +Assuming a set of blueprints where we can cut camera's a on a vision mixer's mix effect by using adlib pieces, we want to add a fast path where the camera input is changed through the datastore first and then afterwards we add the piece for correctness. + +1. If you haven't yet, convert the current camera adlibs to adlib actions by exporting the `IBlueprintActionManifest` as part of your `getRundown` implementation and implementing an adlib action in your `executeAction` handler that adds your camera piece. +2. Modify any camera pieces (including the one from your adlib action) to contain a reference to the datastore (See the timeline API example) +3. Implement an `executeDataStoreAction` handler as part of your blueprints, when this handler receives the action for your camera adlib it should call the `setTimelineDatastoreValue` method with the key you used in the timeline object (In the example it's `camInput`), the new input for the vision mixer and the `DatastorePersistenceMode.Temporary` persistence mode. diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/intro.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/intro.md new file mode 100644 index 0000000000..6b5caa33ca --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/intro.md @@ -0,0 +1,15 @@ +--- +sidebar_label: Introduction +sidebar_position: 1 +--- + +# For Developers + +The pages below are intended for developers of any of the Sofie-related repos and/or blueprints. + +A read-through of the [Concepts & Architectures](../user-guide/concepts-and-architecture.md) is recommended, before diving too deep into development. + +- [Libraries](libraries.md) +- [Contribution Guidelines](contribution-guidelines.md) +- [For Blueprint Developers](for-blueprint-developers/intro.md) +- [API Documentation](api-documentation.md) diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/json-config-schema.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/json-config-schema.md new file mode 100644 index 0000000000..1d6df1db25 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/json-config-schema.md @@ -0,0 +1,209 @@ +--- +sidebar_label: JSON Config Schema +sidebar_position: 7 +--- + +# JSON Config Schema + +So that Sofie does not have to be aware of every type of gateway that may connect to it, each gateway provides a manifest describing itself and the configuration fields that it has. + +Since version 1.50, this is done using [JSON Schemas](https://json-schema.org/). This allows schemas to be written, with typescript interfaces generated from the schema, and for the same schema to be used to render a flexible UI. +We recommend using [json-schema-to-typescript](https://github.com/bcherny/json-schema-to-typescript) to generate typescript interfaces. + +Only a subset of the JSON Schema specification is supported, and some additional properties are used for the UI. + +We expect this subset to grow over time as more sections are found to be useful to us, but we may proceed cautiously to avoid constantly breaking other applications that use TSR and these schemas. + +## Non-standard properties + +We use some non-standard properties to help the UI render with friendly names. + +### `ui:category` + +Note: Only valid for blueprint configuration. + +Category of the property + +### `ui:title` + +Title of the property + +### `ui:description` + +Description/hint for the property + +### `ui:summaryTitle` + +If set, when in a table this property will be used as part of the summary with this label + +### `ui:zeroBased` + +If an integer property, whether to treat it as zero-based + +### `ui:displayType` + +Override the presentation with a special mode. +Currently only valid for string properties. Valid values are 'json'. + +### `tsEnumNames` + +This is primarily for `json-schema-to-typescript`. + +Names of the enum values as generated for the typescript enum, which we display in the UI instead of the raw values + +### `ui:sofie-enum` & `ui:sofie-enum:filter` + +Note: Only valid for blueprint configuration. + +Sometimes it can be useful to reference other values. This property can be used on string fields, to let sofie generate a dropdown populated with values valid in the current context. + +#### `mappings` + +Valid for both show-style and studio blueprint configuration + +This will provide a dropdown of all mappings in the studio, or studios where the show-style can be used. + +Setting `ui:sofie-enum:filter` to an array of strings will filter the dropdown by the specified DeviceType. + +#### `source-layers` + +Valid for only show-style blueprint configuration. + +This will provide a dropdown of all source-layers in the show-style. + +Setting `ui:sofie-enum:filter` to an array of numbers will filter the dropdown by the specified SourceLayerType. + +## Supported types + +Any JSON Schema property or type is allowed, but will be ignored if it is not supported. + +In general, if a `default` is provided, we will use that as a placeholder in the input field. + +### `object` + +This should be used as the root of your schema, and can be used anywhere inside it. The properties inside any object will be shown if they are supported. + +You may want to set the `title` property to generate a typescript interface for it. + +See the examples to see how to create a table for an object. + +`ui:displayType` can be set to `json` to allow for manual editing of an arbitrary json object. + +### `integer` + +`enum` can be set with an array of values to turn it into a dropdown. + +### `number` + +### `boolean` + +### `string` + +`enum` can be set with an array of values to turn it into a dropdown. + +`ui:sofie-enum` can be used to make a special dropdown. + +### `array` + +The behaviour of this depends on the type of the `items`. + +#### `string` + +`enum` can be set with an array of values to turn it into a dropdown + +`ui:sofie-enum` can be used to make a special dropdown. + +Otherwise is treated as a multi-line string, stored as an array of strings. + +#### `object` + +This is not available in all places we use this schema. For example, Mappings are unable to use this, but device configuration is. Additionally, using it inside of another object-array is not allowed. + +## Examples + +Below is an example of a simple schema for a gateway configuration. The subdevices are handled separetely, with their own schema. + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/product.schema.json", + "title": "Mos Gateway Config", + "type": "object", + "properties": { + "mosId": { + "type": "string", + "ui:title": "MOS ID of Mos-Gateway (Sofie MOS ID)", + "ui:description": "MOS ID of the Sofie MOS device (ie our ID). Example: sofie.mos", + "default": "" + }, + "debugLogging": { + "type": "boolean", + "ui:title": "Activate Debug Logging", + "default": false + } + }, + "required": ["mosId"], + "additionalProperties": false +} +``` + +### Defining a table as an object + +In the generated typescript interface, this will produce a property `"TestTable": { [id: string]: TestConfig }`. + +The key part here, is that it is an object with no `properties` defined, and a single `patternProperties` value performing a catchall. + +An `object` table is better than an `array` in blueprint-configuration, as it allows the UI to override individual values, instead of the table as a whole. + +```json +"TestTable": { + "type": "object", + "ui:category": "Test", + "ui:title": "Test table", + "ui:description": "", + "patternProperties": { + "": { + "type": "object", + "title": "TestConfig", + "properties": { + "number": { + "type": "integer", + "ui:title": "Number", + "ui:description": "Camera number", + "ui:summaryTitle": "Number", + "default": 1, + "min": 0 + }, + "port": { + "type": "integer", + "ui:title": "Port", + "ui:description": "ATEM Port", + "default": 1, + "min": 0 + } + }, + "required": ["number", "port"], + "additionalProperties": false + } + }, + "additionalProperties": false +}, + +``` + +### Select multiple ATEM device mappings + +```json +"mappingId": { + "type": "array", + "ui:title": "Mapping", + "ui:description": "", + "ui:summaryTitle": "Mapping", + "items": { + "type": "string", + "ui:sofie-enum": "mappings", + "ui:sofie-enum:filter": ["ATEM"], + }, + "uniqueItems": true +}, +``` diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/libraries.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/libraries.md new file mode 100644 index 0000000000..2352cc0ed8 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/libraries.md @@ -0,0 +1,62 @@ +--- +description: List of all repositories related to Sofie +sidebar_position: 5 +--- + +# Applications & Libraries + +## Main Application + +[**Sofie Core**](https://github.com/nrkno/sofie-core) is the main application that serves the web GUI and handles the core logic. + +## Gateways and Services + +Together with the _Sofie Core_ there are several _gateways_ which are separate applications, but which connect to _Sofie Core_ and are managed from within the Core's web UI. + +* [**Playout Gateway**](https://github.com/nrkno/sofie-core/tree/master/packages/playout-gateway) Handles the playout from _Sofie_. Connects to and controls a multitude of devices, such as vision mixers, graphics, light controllers, audio mixers etc.. +* [**MOS Gateway**](https://github.com/nrkno/sofie-core/tree/master/packages/mos-gateway) Connects _Sofie_ to a newsroom system \(NRCS\) and ingests rundowns via the [MOS protocol](http://mosprotocol.com/). +* [**Live Status Gateway**](https://github.com/nrkno/sofie-core/tree/master/packages/live-status-gateway) Allows external systems to subscribe to state changes in Sofie. +* [**iNEWS Gateway**](https://github.com/tv2/inews-ftp-gateway) Connects _Sofie_ to an Avid iNEWS newsroom system. +* [**Spreadsheet Gateway**](https://github.com/SuperFlyTV/spreadsheet-gateway) Connects _Sofie_ to a _Google Drive_ folder and ingests rundowns from _Google Sheets_. +* [**Input Gateway**](https://github.com/nrkno/sofie-input-gateway) Connects _Sofie_ to various input devices, allowing triggering _User-Actions_ using these devices. +* [**Package Manager**](https://github.com/nrkno/sofie-package-manager) Handles media asset transfer and media file management for pulling new files, deleting expired files on playout devices and generating additional metadata (previews, thumbnails, automated QA checks) in a more performant, and possibly distributed, way. Can smartly figure out how to get a file on storage A to playout server B. + + +## Libraries + +There are a number of libraries used in the Sofie ecosystem: + +* [**ATEM Connection**](https://github.com/nrkno/sofie-atem-connection) Library for communicating with Blackmagic Design's ATEM mixers +* [**ATEM State**](https://github.com/nrkno/sofie-atem-state) Used in TSR to tracks the state of ATEMs and generate commands to control them. +* [**CasparCG Server Connection**](https://github.com/SuperFlyTV/casparcg-connection) developed by **[_SuperFly.tv_](https://github.com/SuperFlyTV)** Library to connect and interact with CasparCG Servers. +* [**CasparCG State**](https://github.com/superflytv/casparcg-state) developed by **[_SuperFly.tv_](https://github.com/SuperFlyTV)** Used in TSR to tracks the state of CasparCG Servers and generate commands to control them. +* [**Ember+ Connection**](https://github.com/nrkno/sofie-emberplus-connection) Library to communicate with _Ember+_ control protocol +* [**HyperDeck Connection**](https://github.com/nrkno/sofie-hyperdeck-connection) Library for connecting to Blackmagic Design's HyperDeck recorders. +* [**MOS Connection**](https://github.com/nrkno/sofie-mos-connection/) A [_MOS protocol_](http://mosprotocol.com/) library for acting as a MOS device and connecting to an newsroom control system. +* [**Quantel Gateway Client**](https://github.com/nrkno/sofie-quantel-gateway-client) An interface that talks to the Quantel-Gateway application. +* [**Sofie Core Integration**](https://github.com/nrkno/sofie-core-integration) Used to connect to the [Sofie Core](https://github.com/nrkno/sofie-core) by the Gateways. +* [**Sofie Blueprints Integration**](https://github.com/nrkno/sofie-sofie-blueprints-integration) Common types and interfaces used by both Sofie Core and the user-defined blueprints. +* [**SuperFly-Timeline**](https://github.com/SuperFlyTV/supertimeline) developed by **[_SuperFly.tv_](https://github.com/SuperFlyTV)** Resolver and rules for placing objects on a virtual timeline. +* [**ThreadedClass**](https://github.com/nytamin/threadedClass) developed by **[_Nytamin_](https://github.com/nytamin)** Used in TSR to spawn device controllers in separate processes. +* [**Timeline State Resolver**](https://github.com/nrkno/sofie-timeline-state-resolver) \(TSR\) The main driver in **Playout Gateway,** handles connections to playout-devices and sends commands based on a **Timeline** received from **Core**. + + + +There are also a few typings-only libraries that define interfaces between applications: + +* [**Blueprints Integration**](https://www.npmjs.com/package/@sofie-automation/blueprints-integration) Defines the interface between [**Blueprints**](../user-guide/concepts-and-architecture.md#blueprints) and **Sofie Core**. +* [**Timeline State Resolver types**](https://www.npmjs.com/package/timeline-state-resolver-types) Defines the interface between [**Blueprints**](../user-guide/concepts-and-architecture.md#blueprints) and the timeline that will be fed into **TSR** for playout. + +## Other Sofie-related Repositories + +* [**CasparCG Server** \(NRK fork\)](https://github.com/nrkno/sofie-casparcg-server) Sofie-specific fork of CasparCG Server. +* [**CasparCG Launcher**](https://github.com/nrkno/sofie-casparcg-launcher) Launcher, controller, and logger for CasparCG Server. +* [**CasparCG Media Scanner** \(NRK fork\)](https://github.com/nrkno/sofie-casparcg-server) Sofie-specific fork of CasparCG Server 2.2 Media Scanner. +* [**Sofie Chef**](https://github.com/nrkno/sofie-chef) A simple Chromium based renderer, used for kiosk mode rendering of web pages. +* [**Media Manager**](https://github.com/nrkno/sofie-media-management) *(deprecated)* Handles media transfer and media file management for pulling new files and deleting expired files on playout devices. +* [**Quantel Browser Plugin**](https://github.com/nrkno/sofie-quantel-browser-plugin) MOS-compatible Quantel video clip browser for use with Sofie. +* [**Sisyfos Audio Controller**](https://github.com/nrkno/sofie-sisyfos-audio-controller) *developed by [_olzzon_](https://github.com/olzzon/)* +* [**Quantel Gateway**](https://github.com/nrkno/sofie-quantel-gateway) CORBA to REST gateway for _Quantel/ISA_ playback. + + + diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/publications.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/publications.md new file mode 100644 index 0000000000..ed3b377532 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/publications.md @@ -0,0 +1,43 @@ +--- +title: Publications +sidebar_position: 12 +--- + +To ensure that the UI of Sofie is reactive, we are leveraging publications over the DDP connection that Meteor provides. +In its most basic form, this allows for streaming MongoDB document updates as they happen to the UI, and there is also a structure in place for 'Custom Publications' which appear like a MongoDB collection to the client, but are generated in-memory collections of data allowing us to do some processing of data before publishing it to the client. + +It is possible to subscribe to these publications outside of Meteor, but we have not found any maintained ddp clients, except for the one we are using in `server-core-integration`. The protocol is simple and stable and has documentation on the [Meteor GitHub](https://github.com/meteor/meteor/blob/devel/packages/ddp/DDP.md), and should be easy to implement in another language if desired. + +All of the publication implementations reside in [`meteor/server/publications` folder](https://github.com/nrkno/sofie-core/tree/master/meteor/server/publications), and are typically pretty well isolated from the rest of the code we have in Meteor. + +We prefer using publications in Sofie over polling because: + +- there are not enough DDP clients to a single Sofie installation for the number of connected clients to be problematic +- polling can be costly for many of these publications without some form of caching or tracking changes (which starts to get to a similar level of complexity) +- we can be more confident that all the clients have the same data as the database is our point of truth +- the system can be more reactive as changes are pushed to interested parties with minimal intervention + +## MongoDB Publications + +A majority of data is sent to the client utilising Meteor's ability to publish a MongoDB cursor. This allows us to run a MongoDB query on the backend, and let it handle the publishing of individual changes. + +In some (typically older) publications, we let the client specify the MongoDB query to use for the subscription, where we perform some basic validation and authentication before executing the query. + +In typically newer publications, we are formalising the publications a bit better by requiring some simpler parameters to the publication, with the query then generated on the backend. This will help us ensure that the queries are made with suitable indices, and to ensure that subscriptions are deduplicated where possible. + +## Custom Publications + +There has been a recent push towards using more 'custom' publications for streaming data to the UI. While we are unsure if this will be beneficial for every publication, it is really beneficial for others as it allows us to do some pre-computation of data before sending it to the client. + +To achieve this, we have an `optimisedObserver` flow which is designed to help maange to a custom publication, with a few methods to fill in to setup the reactivity and the data transformation. + +One such publication is the `PieceContentStatus`, prior to version 1.50, this was computed inside the UI. +A brief overview of this publication, is that it looks at each Piece in a Rundown, and reports whether the Piece is 'OK'. This check is primarily focussed on Pieces containing clips, where it will check the metadata generated by either package manager or media manager to ensure that the clip is marked as being ready for playout, and that it has the correct format and some other quality checks. + +To do this on the client meant needing to subscribe to the whole contents of a couple of MongoDB collections, as it is not easy to determine which documents will be needed until the check is being run. This caused some issues as these collections could get rather large. We also did not always have every Piece loaded in the UI, so had to defer some of the computation to the backend via polling. + +This makes it more suitable for a custom publication, where we can more easily and cheaply do this computation without being concerned about causing UI lockups and with less concern about memory pressure. Performing very granular MongoDB queries is also cheaper. The result is that we build a graph of what other documents are used for the status of each Piece, so we can cheaply react to changes to any of those documents, while also watching for changes to the pieces. + +## Live Status Gateway + +The Live Status Gateway was introduced to Sofie in version 1.50. This gateway serves as a way for an external system to subscribe to publications which are designed to be simpler than the ones we publish over DDP. These publications are intended to be used by external systems which need a 'stable' API and to not have too much knowledge about the inner workings of Sofie. See [Api Stability](./api-stability.md) for more details. diff --git a/packages/documentation/versioned_docs/version-1.50.0/for-developers/worker-threads-and-locks.md b/packages/documentation/versioned_docs/version-1.50.0/for-developers/worker-threads-and-locks.md new file mode 100644 index 0000000000..f20a47a567 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/for-developers/worker-threads-and-locks.md @@ -0,0 +1,61 @@ +--- +title: Worker Threads & Locks +sidebar_position: 9 +--- + +Starting with v1.40.0 (Release 40), the core logic of Sofie is split across +multiple threads. This has been done to minimise performance bottlenecks such as ingest changes delaying takes. In its +current state, it should not impact deployment of Sofie. + +In the initial implementation, these threads are run through [threadedClass](https://github.com/nytamin/threadedclass) +inside of Meteor. As Meteor does not support the use of `worker_threads`, and to allow for future separation, the +`worker_threads` are treated and implemented as if they are outside of the Meteor ecosystem. The code is isolated from +Meteor inside of `packages/job-worker`, with some shared code placed in `packages/corelib`. + +Prior to v1.40.0, there was already a work-queue of sorts in Meteor. As such the functions were defined pretty well to +translate across to being on a true work queue. For now this work queue is still in-memory in the Meteor process, but we +intend to investigate relocating this in a future release. This will be necessary as part of a larger task of allowing +us to scale Meteor for better resiliency. Many parts of the worker system have been designed with this in mind, and so +have sufficient abstraction in place already. + +### The Worker + +The worker process is designed to run the work for one or more studios. The initial implementation will run for all +studios in the database, and is monitoring for studios to be added or removed. + +For each studio, the worker runs 3 threads: + +1. The Studio/Playout thread. This is where all the playout operations are executed, as well as other operations that + require 'ownership' of the Studio +2. The Ingest thread. This is where all the MOS/Ingest updates are handled and fed through the bluerpints. +3. The events thread. Some low-priority tasks are pushed to here. Such as notifying ENPS about _the yellow line_, or the + Blueprints methods used to generate External-Messages for As-Run Log. + +In future it is expected that there will be multiple ingest threads. How the work will be split across them is yet to be +determined + +### Locks + +At times, the playout and ingest threads both need to take ownership of `RundownPlaylists` and `Rundowns`. + +To facilitate this, there are a couple of lock types in Sofie. These are coordinated by the parent thread in the worker +process. + +#### PlaylistLock + +This lock gives ownership of a specific `RundownPlaylist`. It is required to be able to load a `CacheForPlayout`, and +must be held during other times where the `RundownPlaylist` is modified or is expected to not change. + +This lock must be held while writing any changes to either a `RundownPlaylist` or any `Rundown` that belong to the +`RundownPlaylist`. This ensures that any writes to MongoDB are atomic, and that Sofie doesn't start performing a +playout operation halfway through an ingest operation saving. + +#### RundownLock + +This lock gives ownership of a specific `Rundown`. It is required to be able to load a `CacheForIngest`, and must held +during other times where the `Rundown` is modified or is expected to not change. + +:::caution +It is not allowed to aquire a `RundownLock` while inside of a `PlaylistLock`. This is to avoid deadlocks, as it is very +common to aquire a `PlaylistLock` inside of a `RundownLock` +::: diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/concepts-and-architecture.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/concepts-and-architecture.md new file mode 100644 index 0000000000..bce331a9f7 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/concepts-and-architecture.md @@ -0,0 +1,192 @@ +--- +sidebar_position: 1 +--- + +# Concepts & Architecture + +## System Architecture + +![Example of a Sofie setup with a Playout Gateway and a Spreadsheet Gateway](/img/docs/main/features/playout-and-spreadsheet-example.png) + +### Sofie Core + +**Sofie Core** is a web server which handle business logic and serves the web GUI. +It is a [NodeJS](https://nodejs.org/) process backed up by a [MongoDB](https://www.mongodb.com/) database and based on the framework [Meteor](http://meteor.com/). + +### Gateways + +Gateways are applications that connect to Sofie Core and and exchanges data; such as rundown data from an NRCS or the [Timeline](#timeline) for playout. + +An examples of a gateways is the [Spreadsheet Gateway](https://github.com/SuperFlyTV/spreadsheet-gateway). +All gateways use the [Core Integration Library](https://github.com/nrkno/sofie-core/tree/master/packages/server-core-integration) to communicate with Core. + +## System, \(Organization\), Studio & Show Style + +To be able to facilitate various workflows and to Here's a short explanation about the differences between the "System", "Organization", "Studio" and "Show Style". + +- The **System** defines the whole of the Sofie Core +- The **Organization** \(only available if user accounts are enabled\) defines things that are common for an organization. An organization consists of: **Users, Studios** and **ShowStyles**. +- The **Studio** contains things that are related to the "hardware" or "rig". Technically, a Studio is defined as an entity that can have one \(or none\) rundown active at any given time. In most cases, this will be a representation of your gallery, with cameras, video playback and graphics systems, external inputs, sound mixers, lighting controls and so on. A single System can easily control multiple Studios. +- The **Show Style** contains settings for the "show", for example if there's a "Morning Show" and an "Afternoon Show" - produced in the same gallery - they might be two different Show Styles \(played in the same Studio\). Most importantly, the Show Style decides the "look and feel" of the Show towards the producer/director, dictating how data ingested from the NRCS will be interpreted and how the user will interact with the system during playback (see: [Show Style](../configuration/settings-view#show-style) in Settings). + * A **Show Style Variant** is a set of Show Style _Blueprint_ configuration values, that allows to use the same interaction model across multiple Shows with potentially different assets, changing the outward look of the Show: for example news programs with different hosts produced from the same Studio, but with different light setups, backscreen and overlay graphics. + +![Sofie Architecture Venn Diagram](/img/docs/main/features/sofie-venn-diagram.png) + +## Playlists, Rundowns, Segments, Parts, Pieces + +![Playlists, Rundowns, Segments, Parts, Pieces](/img/docs/main/features/playlist-rundown-segment-part-piece.png) + +### Playlist + +A Playlist \(or "Rundown Playlist"\) is the entity that "goes on air" and controls the playhead/Take Point. + +It contains one or several Rundowns inside, which are playout out in order. + +:::info +In some many studios, there is only ever one rundown in a playlist. In those cases, we sometimes lazily refer to playlists and rundowns as "being the same thing". +::: + +A Playlist is played out in the context of it's [Studio](#studio), thereby only a single Playlist can be active at a time within each Studio. + +A playlist is normally played through and then ends but it is also possible to make looping playlists in which case the playlist will start over from the top after the last part has been played. + +### Rundown + +The Rundown contains the content for a show. It contains Segments and Parts, which can be selected by the user to be played out. +A Rundown always has a [showstyle](#showstyle) and is played out in the context of the [Studio](#studio) of its Playlist. + +### Segment + +The Segment is the horizontal line in the GUI. It is intended to be used as a "chapter" or "subject" in a rundown, where each individual playable element in the Segment is called a [Part](#part). + +### Part + +The Part is the playable element inside of a [Segment](#segment). This is the thing that starts playing when the user does a [TAKE](#take-point). A Playing part is _On Air_ or _current_, while the part "cued" to be played is _Next_. +The Part in itself doesn't determine what's going to happen, that's handled by the [Pieces](#piece) in it. + +### Piece + +The Pieces inside of a Part determines what's going to happen, the could be indicating things like VT's, cut to cameras, graphics, or what script the host is going to read. + +Inside of the pieces are the [timeline-objects](#what-is-the-timeline) which controls the playout on a technical level. + +:::tip +Tip! If you want to manually play a certain piece \(for example a graphics overlay\), you can at any time double-click it in the GUI, and it will be copied and played at your play head, just like an [AdLib](#adlib-pieces) would! +::: + +See also: [Showstyle](#system-organization-studio--show-style) + +### AdLib Piece + +The AdLib pieces are Pieces that isn't programmed to fire at a specific time, but instead intended to be manually triggered by the user. + +The AdLib pieces can either come from the currently playing Part, or it could be _global AdLibs_ that are available throughout the show. + +An AdLib isn't added to the Part in the GUI until it starts playing, instead you find it in the [Shelf](features/sofie-views.mdx#shelf). + +## Buckets + +A Bucket is a container for AdLib Pieces created by the producer/operator during production. They exist independently of the Rundowns and associated content created by ingesting data from the NRCS. Users can freely create, modify and remove Buckets. + +The primary use-case of these elements is for breaking news formats where quick turnaround video editing may require circumvention of the regular flow of show assets and programming via the NRCS. Currently, one way of creating AdLibs inside Buckets is using a MOS Plugin integration inside the Shelf, where MOS [ncsItem](https://mosprotocol.com/wp-content/MOS-Protocol-Documents/MOS-Protocol-2.8.4-Current.htm#ncsItem) elements can be dragged from the MOS Plugin onto a bucket and ingested. + +The ingest happens via the `getAdlibItem` method: [https://github.com/nrkno/sofie-core/blob/master/packages/blueprints-integration/src/api.ts#L215](https://github.com/nrkno/sofie-core/blob/master/packages/blueprints-integration/src/api.ts#L215) + +## Views + +Being a web-based system, Sofie has a number of customisable, user-facing web [views](features/sofie-views.mdx) used for control and monitoring. + +## Blueprints + +Blueprints are plug-ins that run in Sofie Core. They interpret the data coming in from the rundowns and transform them into a rich set of playable elements \(Segments, Parts, AdLibs etc\). + +The blueprints are webpacked javascript bundles which are uploaded into Sofie via the GUI. They are custom-made and changes depending on the show style, type of input data \(NRCS\) and the types of controlled devices. A generic [blueprint that works with spreadsheets is available here](https://github.com/SuperFlyTV/sofie-demo-blueprints). + +When [Sofie Core](#sofie-core) calls upon a Blueprint, it returns a JavaScript object containing methods callable by Sofie Core. These methods will be called by Sofie Core in different situations, depending on the method. +Documentation on these interfaces are available in the [Blueprints integration](https://www.npmjs.com/package/@sofie-automation/blueprints-integration) library. + +There are 3 types of blueprints, and all 3 must be uploaded into Sofie before the system will work correctly. + +### System Blueprints + +Handle things on the _System level_. +Documentation on the interface to be exposed by the Blueprint: +[https://github.com/nrkno/sofie-core/blob/master/packages/blueprints-integration/src/api.ts#L75](https://github.com/nrkno/sofie-core/blob/master/packages/blueprints-integration/src/api.ts#L75) + +### Studio Blueprints + +Handle things on the _Studio level_, like "which showstyle to use for this rundown". +Documentation on the interface to be exposed by the Blueprint: +[https://github.com/nrkno/sofie-core/blob/master/packages/blueprints-integration/src/api.ts#L85](https://github.com/nrkno/sofie-core/blob/master/packages/blueprints-integration/src/api.ts#L85) + +### Showstyle Blueprints + +Handle things on the _Showstyle level_, like generating [_Baseline_](#baseline), _Segments_, _Parts, Pieces_ and _Timelines_ in a rundown. +Documentation on the interface to be exposed by the Blueprint: +[https://github.com/nrkno/sofie-core/blob/master/packages/blueprints-integration/src/api.ts#L117](https://github.com/nrkno/sofie-core/blob/master/packages/blueprints-integration/src/api.ts#L117) + +## `PartInstances` and `PieceInstances` + +In order to be able to facilitate ingesting changes from the NRCS while continuing to provide a stable and predictable playback of the Rundowns, Sofie internally uses a concept of ["instantiation"](https://en.wikipedia.org/wiki/Instance_(computer_science)) of key Rundown elements. Before playback of a Part can begin, the Part and it's Pieces are copied into an Instance of a Part: a `PartInstance`. This protects the contents of the _Next_ and _On Air_ part, preventing accidental changes that could surprise the producer/director. This also makes it possible to inspect the "as played" state of the Rundown, independently of the "as planned" state ingested from the NRCS. + +The blueprints can optionally allow some changes to the Parts and Pieces to be forwarded onto these `PartInstances`: [https://github.com/nrkno/sofie-core/blob/master/packages/blueprints-integration/src/api.ts#L190](https://github.com/nrkno/sofie-core/blob/master/packages/blueprints-integration/src/api.ts#L190) + +## Timeline + +### What is the timeline? + +The Timeline is a collection of timeline-objects, that together form a "target state", i.e. an intent on what is to be played and at what times. + +The timeline-objects can be programmed to contain relative references to each other, so programming things like _"play this thing right after this other thing"_ is as easy as `{start: { #otherThing.end }}` + +The [Playout Gateway](../for-developers/libraries.md) picks up the timeline from Sofie Core and \(using the [TSR timeline-state-resolver](https://github.com/nrkno/sofie-timeline-state-resolver)\) controls the playout devices to make sure that they actually play what is intended. + +![Example of 2 objects in a timeline: The #video object, destined to play at a certain time, and #gfx0, destined to start 15 seconds into the video.](/img/docs/main/features/timeline.png) + +### Why a timeline? + +The Sofie system is made to work with a modern web- and IT-based approach in mind. Therefore, the Sofie Core can be run either on-site, or in an off-site cloud. + +![Sofie Core can run in the cloud](/img/docs/main/features/sofie-web-architecture.png) + +One drawback of running in a cloud over the public internet is the - sometimes unpredictable - latency. The Timeline overcomes this by moving all the immediate control of the playout devices to the Playout Gateway, which is intended to run on a local network, close to the hardware it controls. +This also gives the system a simple way of load-balancing - since the number of web-clients or load on Sofie Core won't affect the playout. + +Another benefit of basing the playout on a timeline is that when programming the show \(the blueprints\), you only have to care about "what you want to be on screen", you don't have to care about cleaning up previously played things, or what was actually played out before. Those are things that are handled by the Playout Gateway automatically. This also allows the user to jump around in a rundown freely, without the risk of things going wrong on air. + +### How does it work? + +:::tip +Fun tip! The timeline in itself is a [separate library available on github](https://github.com/SuperFlyTV/supertimeline). + +You can play around with the timeline in the browser using [JSFiddle and the timeline-visualizer](https://jsfiddle.net/nytamin/rztp517u/)! +::: + +The Timeline is stored by Sofie Core in a MongoDB collection. It is generated whenever a user does a [Take](#take-point), changes the [Next-point](#next-point-and-lookahead) or anything else that might affect the playout. + +_Sofie Core_ generates the timeline using: + +- The [Studio Baseline](#baseline) \(only if no rundown is currently active\) +- The [Showstyle Baseline](#baseline), of the currently active rundown. +- The [currently playing Part](#take-point) +- The [Next'ed Part](#next-point-and-lookahead) and Parts that come after it \(the [Lookahead](#lookahead)\) +- Any [AdLibs](#adlib-pieces) the user has manually selected to play + +The [**Playout Gateway**](../for-developers/libraries.md#gateways) then picks up the new timeline, and pipes it into the [\(TSR\) timeline-state-resolver](https://github.com/nrkno/sofie-timeline-state-resolver) library. + +The TSR then... + +- Resolves the timeline, using the [timeline-library](https://github.com/SuperFlyTV/supertimeline) +- Calculates new target-states for each relevant point in time +- Maps the target-state to each playout device +- Compares the target-states for each device with the currently-tracked-state and.. +- Generates commands to send to each device to account for the change +- The commands are then put on queue and sent to the devices at the correct time + +:::info +For more information about what playout devices _TSR_ supports, and examples of the timeline-objects, see the [README of TSR](https://github.com/nrkno/sofie-timeline-state-resolver#timeline-state-resolver) +::: + +:::info +For more information about how to program timeline-objects, see the [README of the timeline-library](https://github.com/SuperFlyTV/supertimeline#superfly-timeline) +::: diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/_category_.json b/packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/_category_.json new file mode 100644 index 0000000000..d2aee9ef5b --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Configuration", + "position": 4 +} \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/settings-view.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/settings-view.md new file mode 100644 index 0000000000..2a4a3e6a25 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/settings-view.md @@ -0,0 +1,173 @@ +--- +sidebar_position: 2 +--- +# Settings View + +:::caution +The settings views are only visible to users with the correct [access level](../features/access-levels.md)! +::: + +Recommended read before diving into the settings: [System, \(Organization\), Studio & Show Style](../concepts-and-architecture.md#system-organization-studio-and-show-style). + +## System + +The _System_ settings are settings for this installation of Sofie. In here goes the settings that are applicable system-wide. + +:::caution +Documentation for this section is yet to be written. +::: + +### Name and logo + +Sofie contains the option to change the name of the installation. This is useful to identify different studios or regions. + +We have also provided some seasonal logos just for fun. + +### System-wide notification message + +This option will show a notification to the user containing some custom text. This can be used to inform the user about on-going problems or maintenance information. + +### Support panel + +The support panel is shown in the rundown view when the user clicks the "?" button in the right bottom corner. It can contain some custom HTML which can be used to refer your users to custom information specific to your organisation. + +### Action triggers + +The action triggers section lets you set custom keybindings for system-level actions such as doing a take or resetting a rundown. + +### Monitoring + +Sofie can be configured to send information to Elastic APM. This can provide useful information about the system's performance to developers. In general this can reduce the performance of Sofie altogether though so it is recommended to disable it in production. + +Sofie can also monitor for blocked threads, and will log a message if it discovers any. This is also recommended to disable in production. + +### CRON jobs + +Sofie contains cron jobs for restarting any casparcg servers through the casparcg launcher as well as a job to create rundown snapshots periodically. + +### Clean up + +The clean up process in Sofie will search the database for unused data and indexes and removes them. If you have had an installation running for many versions this may increase database informance and is in general safe to use at any time. + +## Studio + +A _Studio_ in Sofie-terms is a physical location, with a specific set of devices and equipment. Only one show can be on air in a studio at the same time. +The _studio_ settings are settings for that specific studio, and contains settings related to hardware and playout, such as: + +* **Attached devices** - the Gateways related to this studio +* **Blueprint configuration** - custom config option defined by the blueprints +* **Layer Mappings** - Maps the logical _timeline layers_ to physical devices and outputs + +The Studio uses a studio-blueprint, which handles things like mapping up an incoming rundown to a Showstyle. + +### Attached Devices + +This section allows you to add and remove Gateways that are related to this _Studio_. When a Gateway is attached to a Studio, it will react to the changes happening within it, as well as feed the neccessary data into it. + +### Blueprint Configuration + +Sofie allows the Blueprints to expose custom configuration fields that allow the System Administrator to reconfigure how these Blueprints work through the Sofie UI. Here you can change the configuration of the [Studio Blueprint](../concepts-and-architecture.md#studio-blueprints). + +### Layer Mappings + +This section allows you to add, remove and configure how logical device-control will be translated to physical automation control. [Blueprints](../concepts-and-architecture.md#blueprints) control devices through objects placed on a [Timeline](../concepts-and-architecture.md#timeline) using logical device identifiers called _Layers_. A layer represents a single aspect of a device that can be controlled at a given time: a video switcher's M/E bus, an audio mixers's fader, an OSC control node, a video server's output channel. Layer Mappings translate these logical identifiers into physical device aspects, for example: + +![A sample configuration of a Layer Mapping for the M/E1 Bus of an ATEM switcher](/img/docs/main/features/atem-layer-mapping-example.png) + +This _Layer Mapping_ configures the `atem_me_program` Timeline-layer to control the `atem0` device of the `ATEM` type. No Lookahead will be enabled for this layer. This layer will control a `MixEffect` aspect with the Index of `0` \(so M/E 1 Bus\). + +These mappings allow the System Administrator to reconfigure what devices the Blueprints will control, without the need of changing the Blueprint code. + +#### Route Sets + +In order to allow the Producer to reconfigure the automation from the Switchboard in the [Rundown View](../concepts-and-architecture.md#rundown-view), as well as have some pre-set automation control available for the System Administrator, Sofie has a concept of Route Sets. Route Sets work on top of the Layer Mappings, by configuring sets of [Layer Mappings](settings-view.md#layer-mappings) that will re-route the control from one device to another, or to disable the automation altogether. These Route Sets are presented to the Producer in the [Switchboard](../concepts-and-architecture.md#switchboard) panel. + +A Route Set is essentially a distinct set of Layer Mappings, which can modify the settings already configured by the Layer Mappings, but can be turned On and Off. Called Routes, these can change: + +* the Layer ID to a new Layer ID +* change the Device being controlled by the Layer +* change the aspect of the Device that's being controlled. + +Route Sets can be grouped into Exclusivity Groups, in which only a single Route Set can be enabled at a time. When activating a Route Set within an Exclusivity Group, all other Route Sets in that group will be deactivated. This in turn, allows the System Administrator to create entire sections of exclusive automation control within the Studio that the Producer can then switch between. One such example could be switching between Primary and Backup playout servers, or switching between Primary and Backup talent microphone. + +![The Exclusivity Group Name will be displayed as a header in the Switchboard panel](/img/docs/main/features/route-sets-exclusivity-groups.png) + +A Route Set has a Behavior property which will dictate what happens how the Route Set operates: + +| Type | Behavior | +| :-------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `ACTIVATE_ONLY` | This RouteSet cannot be deactivated, only a different RouteSet in the same Exclusivity Group can cause it to deactivate | +| `TOGGLE` | The RouteSet can be activated and deactivated. As a result, it's possible for the Exclusivity Group to have no Route Set active | +| `HIDDEN` | The RouteSet can be activated and deactivated, but it will not be presented to the user in the Switchboard panel | + +![An active RouteSet with a single Layer Mapping being re-configured](/img/docs/main/features/route-set-remap.png) + +Route Sets can also be configured with a _Default State_. This can be used to contrast a normal, day-to-day configuration with an exceptional one \(like using a backup device\) in the [Switchboard](../concepts-and-architecture#switchboard) panel. + +| Default State | Behavior | +| :------------ | :------------------------------------------------------------ | +| Active | If the Route Set is not active, an indicator will be shown | +| Not Active | If the Route Set is active, an indicator will be shown | +| Not defined | No indicator will be shown, regardless of the Route Set state | + +## Show style + +A _Showstyle_ is related to the looks and logic of a _show_, which in contrast to the _studio_ is not directly related to the hardware. +The Showstyle contains settings like + +* **Source Layers** - Groups different types of content in the GUI +* **Output Channels** - Indicates different output targets \(such as the _Program_ or _back-screen in the studio_\) +* **Action Triggers** - Select how actions can be started on a per-show basis, outside of the on-screen controls +* **Blueprint configuration** - custom config option defined by the blueprints + +:::caution +Please note the difference between _Source Layers_ and _timeline-layers_: + +[Pieces](../concepts-and-architecture.md#piece) are put onto _Source layers_, to group different types of content \(such as a VT or Camera\), they are therefore intended only as something to indicate to the user what is going to be played, not what is actually going to happen on the technical level. + +[Timeline-objects](../concepts-and-architecture.md#timeline-object) \(inside of the [Pieces](../concepts-and-architecture.md#piece)\) are put onto timeline-layers, which are \(through the Mappings in the studio\) mapped to physical devices and outputs. +The exact timeline-layer is never exposed to the user, but instead used on the technical level to control playout. + +An example of the difference could be when playing a VT \(that's a Source Layer\), which could involve all of the timeline-layers _video\_player0_, _audio\_fader\_video_, _audio\_fader\_host_ and _mixer\_pgm._ +::: + +### Action Triggers + +This is a way to set up how - outside of the Point-and-Click Graphical User Interface - actions can be performed in the User Interface. Commonly, these are the *hotkey combinations* that can be used to either trigger AdLib content or other actions in the larger system. This is done by creating sets of Triggers and Actions to be triggered by them. These pairs can be set at the Show Style level or at the _Sofie Core_ (System) level, for common actions such as doing a Take or activating a Rundown, where you want a shared method of operation. _Sofie Core_ migrations will set up a base set of basic, system-wide Action Triggers for interacting with rundowns, but they can be changed by the System blueprint. + +![Action triggers define modes of interacting with a Rundown](/img/docs/main/features/action_triggers_3.png) + +#### Triggers + +The triggers are designed to be either client-specific or issued by a peripheral device module. + +Currently, the Action Triggers system supports setting up two types of triggeers: Hotkeys and Device Triggers. + +Hotkeys are valid in the scope of a browser window and can be either a single key, a combination of keys (*combo*) or a *chord* - a sequnece of key combinations pressed in a particular order. *Chords* are popular in some text editing applications and vastly expand the amount of actions that can be triggered from a keyboard, at the expense of the time needed to execute them. Currently, the Hotkey editor in Sofie does not support creating *Chords*, but they can be specified by Blueprints during migrations. + +To edit a given trigger, click on the trigger pill on the left of the Trigger-Action set. When hovering, a **+** sign will appear, allowing you to add a new trigger to the set. + +Device Triggers are valid in the scope of a Studio and will be evaluated on the currently active Rundown in a given Studio. To use Device Triggers, you need to have at least a single [Input Gateway](../installation/installing-input-gateway) attached to a Studio and a Device configured in the Input Gateway. Once that's done, when selecting a **Device** trigger type in the pop-up, you can invoke triggers on your Input Device and you will see a preview of the input events shown at the bottom of the pop-up. You can select which of these events should be the trigger by clicking on one of the previews. Note, that some devices differentiate between _Up_ and _Down_ triggers, while others don't. Some may also have other activites that can be done _to_ a trigger. What they are and how they are identified is device-specific and is best discovered through interaction with the device. + +#### Actions + +The actions are built using a base *action* (such as *Activate a Rundown* or *AdLib*) and a set of *filters*, limiting the scope of the *action*. Optionally, some of these *actions* can take additional *parameters*. These filters can operate on various types of objects, depending on the action in question. All actions currently require that the chain of filters starts with scoping out the Rundown the action is supposed to affect. Currently, there is only one type of Rundown-level filter supported: "The Rundown currently in view". + +The Action Triggers user interface guides the user in a wizzard-like fashion through the available *filter* options on a given *action*. + +![Actions can take additional parameters](/img/docs/main/features/action_triggers_2.png) + +If the action provides a preview of the triggered items and there is an available matching Rundown, a preview will be displayed for the matching objects in that Rundown. The system will select the current active rundown, if it is of the currently-edited ShowStyle, and if not, it will select the first available Rundown of the currently-edited ShowStyle. + +![A preview of the action, as scoped by the filters](/img/docs/main/features/action_triggers_4.png) + +Clicking on the action and filter pills allows you to edit the action parameters and filter parameters. *Limit* limits the amount of objects to only the first *N* objects matched - this can significantly improve performance on large data sets. *Pick* and *Pick last* filters end the chain of the filters by selecting a single item from the filtered set of objects (the *N-th* object from the beginning or the end, respectively). *Pick* implicitly contains a *Limit* for the performance improvement. This is not true for *Pick last*, though. + +## Migrations + +The migrations are automatic setup-scripts that help you during initial setup and system upgrades. + +There are system-migrations that comes directly from the version of _Sofie Core_ you're running, and there are also migrations added by the different blueprints. + +It is mandatory to run migrations when you've upgraded _Sofie Core_ to a new version, or upgraded your blueprints. + diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/sofie-core-settings.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/sofie-core-settings.md new file mode 100644 index 0000000000..2c3599a7fe --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/configuration/sofie-core-settings.md @@ -0,0 +1,111 @@ +--- +sidebar_position: 1 +--- + +# Sofie Core: System Configuration + +_Sofie Core_ is configured at it's most basic level using a settings file and environment variables. + +### Environment Variables + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingUseDefault valueExample
+ METEOR_SETTINGS + Contents of settings file (see below) + $(cat settings.json) +
+ TZ + The default time zone of the server (used in logging) + Europe/Amsterdam +
+ MAIL_URL + + Email server to use. See{' '} + https://docs.meteor.com/api/email.html + + smtps://USERNAME:PASSWORD@HOST:PORT +
+ LOG_TO_FILE + File path to log to file + /logs/core/ +
+ +### Settings File + +The settings file is an optional JSON file that contains some configuration settings for how the _Sofie Core_ works and behaves. + +To use a settings file: + +- During development: `meteor --settings settings.json` +- During prod: environment variable \(see above\) + +The structure of the file allows for public and private fields. At the moment, Sofie only uses public fields. Below is an example settings file: + +```text +{ + "public": { + "frameRate": 25 + } +} +``` + +There are various settings you can set for an installation. See the list below: + +| **Field name** | Use | Default value | +| :---------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | :------------------------------------- | +| `defaultToCollapsedSegments` | Should all segments be collapsed by default, until the user expands them | `false` | +| `autoRewindLeavingSegment` | Should segments be automatically rewound after they stop playing | `false` | +| `disableBlurBorder` | Should a border be displayed around the Rundown View when it's not in focus and studio mode is enabled | `false` | +| `defaultTimeScale` | An arbitrary number, defining the default zoom factor of the Timelines | `1` | +| `allowGrabbingTimeline` | Can Segment Timelines be grabbed to scroll them? | `true` | +| `enableUserAccounts` | Enables User Accounts and Authentication. If disabled, all user stations will be treated as a single, anonymous user | `false` | +| `defaultDisplayDuration` | The fallback duration of a Part, when it's expectedDuration is 0. \_\_In milliseconds | `3000` | +| `allowMultiplePlaylistsInGUI` | If true, allows creation of new playlists in the Lobby Gui (rundown list). If false; only pre-existing playlists are allowed. | `false` | +| `followOnAirSegmentsHistory` | How many segments of history to show when scrolling back in time (0 = show current segment only) | `0` | +| `maximumDataAge` | Clean up stuff that are older than this [ms]) | 100 days | +| `poisonKey` | Enable the use of poison key if present and use the key specified. | `'Escape'` | +| `enableNTPTimeChecker` | If set, enables a check to ensure that the system time doesn't differ too much from the speficied NTP server time. | `null` | +| `defaultShelfDisplayOptions` | Default value used to toggle Shelf options when the 'display' URL argument is not provided. | `buckets,layout,shelfLayout,inspector` | +| `enableKeyboardPreview` | The KeyboardPreview is a feature that is not implemented in the main Fork, and is kept here for compatibility | `false` | +| `keyboardMapLayout` | Keyboard map layout (what physical layout to use for the keyboard) | STANDARD_102_TKL | +| `customizationClassName` | CSS class applied to the body of the page. Used to include custom implementations that differ from the main Fork. | `undefined` | +| `useCountdownToFreezeFrame` | If true, countdowns of videos will count down to the last freeze-frame of the video instead of to the end of the video | `true` | +| `confirmKeyCode` | Which keyboard key is used as "Confirm" in modal dialogs etc. | `'Enter'` | + +:::info +The exact definition for the settings can be found [in the code here](https://github.com/nrkno/sofie-core/blob/master/meteor/lib/Settings.ts#L12). +::: diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/faq.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/faq.md new file mode 100644 index 0000000000..e832a36f5c --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/faq.md @@ -0,0 +1,17 @@ +# FAQ + +## What software license does the system use? + +All main components are using the [MIT license](https://opensource.org/licenses/MIT). + +## Is there anything missing in the public repositories? + +Everything needed to install and configure a fully functioning Sofie system is publicly available, with the following exceptions: + +* A rundown data set describing the actual TV show and of media assets. +* Blueprints for your specific show. + +## When will feature _y_ become available? + +Check out the [issues page](https://github.com/nrkno/Sofie-TV-automation/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3ARelease), where there are notes on current and upcoming releases. + diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/_category_.json b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/_category_.json new file mode 100644 index 0000000000..0dd70d8b0e --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Features", + "position": 2 +} \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/access-levels.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/access-levels.md new file mode 100644 index 0000000000..50307f970e --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/access-levels.md @@ -0,0 +1,46 @@ +--- +sidebar_position: 3 +--- +# Access Levels + +A variety of access levels can be set via the URL. By default, a user cannot edit settings, nor play out anything. Some of the access levels provide additional administrative pages or helpful tool tips for new users. These modes are persistent between sessions and will need to be manually disabled by replacing the _1_ with a _0_ in the URL. Below is a quick reference to the modes and what they have access to. + +If user accounts are enabled \(`enableUserAccounts` in [_Sofie Core_ settings](../configuration/sofie-core-settings#settings-file)\), the access levels are set under the user settings. If no user accounts are set, the access level for a browser is set by adding `?theaccessmode=1` to the URL as described below. + +The access level is persisted in browser's Local Storage. To disable, visit`?theaccessmode=0`. + +| Access area | Basic Mode | Configuration Mode | Studio Mode | Admin Mode | +| :--- | :--- | :--- | :--- | :--- | +| **Rundowns** | View Only | View Only | Yes, playout | Yes, playout | +| **Settings** | No | Yes | No | Yes | + + +### Basic mode + +Without enabling any additional modes in Sofie, the browser will have minimal access to the system. It will be able to view a rundown but, will not have the ability to manipulate it. This includes activating, deactivating, or resetting the rundown as well as taking the next part, adlib, etc. + +### Studio mode + +Studio Mode gives the current browser full control of the studio and all information associated to it. This includes allowing actions like activating and deactivating rundowns, taking parts, adlibbing, etc. This mode is accessed by adding a `?studio=1` to the end of the URL. + +### Configuration mode + +Configuration mode gives the user full control over the Settings pages and allows full access to the system including the ability to modify _Blueprints_, _Studios_, or _Show Styles_, creating and restoring _Snapshots_, as well as modifying attached devices. + +### Help Mode + +Enables some tooltips that might be useful to new users. This mode is accessed by adding `?help=1` to the end of the URL. + +### Admin Mode + +This mode will give the user the same access as the _Configuration_ and _Studio_ modes as well as having access to a set of _Test Tools_ and a _Manual Control_ section on the Rundown page. + +This mode is enabled when `?admin=1` is added the end of the URL. + +### Testing Mode + +Enables the page Test Tools, which contains various tools useful for testing the system during development. This mode is enabled when `?testing=1` is added the end of the URL. + +### Developer Mode + +This mode will enable the browsers default right click menu to appear and can be accessed by adding `?develop=1` to the URL. It will also reveal the Manual Control section on the Rundown page. diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/api.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/api.md new file mode 100644 index 0000000000..30d939cfba --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/api.md @@ -0,0 +1,19 @@ +--- +sidebar_position: 10 +--- + +# API + +## Sofie User Actions REST API + +Starting with version 1.50.0, there is a semantically-versioned HTTP REST API definied using the [OpenAPI specification](https://spec.openapis.org/oas/v3.0.3) that exposes some of the functionality available through the GUI in a machine-readable fashion. The API specification can be found in the `packages/openapi` folder. The latest version of this API is available in _Sofie Core_ using the endpoint: `/api/1.0`. There should be no assumption of backwards-compatibility for this API, but this API will be semantically-versioned, with redirects set up for minor-version changes for compatibility. + +There is a also a legacy REST API available that can be used to fetch data and trigger actions. The documentation for this API is minimal, but the API endpoints are listed by _Sofie Core_ using the endpoint: `/api/0` + +## Sofie Live Status Gateway + +Starting with version 1.50.0, there is also a separate service available, called _Sofie Live Status Gateway_, running as a separate process, which will connect to the _Sofie Core_ as a Peripheral Device, listen to the changes of it's state and provide a PubSub service offering a machine-readable view into the system. The WebSocket API is defined using the [AsyncAPI specification](https://v2.asyncapi.com/docs/reference/specification/v2.5.0) and the specification can be found in the `packages/live-status-gateway/api` folder. + +## DDP – Core Integration + +If you're planning to build NodeJS applications that talk to _Sofie Core_, we recommend using the [core-integration](https://github.com/nrkno/sofie-core/tree/master/packages/server-core-integration.md) library, which exposes a number of callable methods and allows for subscribing to data the same way the [Gateways](../concepts-and-architecture.md#gateways) do it. diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/language.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/language.md new file mode 100644 index 0000000000..9fe03d816e --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/language.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 7 +--- +# Language + +_Sofie_ uses the [i18n internationalisation framework](https://www.i18next.com/) that allows you to present user-facing views in multiple languages. + +## Language selection + +The UI will automatically detect user browser's default matching and select the best match, falling back to English. You can also force the UI language to any language by navigating to a page with `?lng=xx` query string, for example: + +`http://localhost:3000/?lng=en` + +This choice is persisted in browser's local storage, and the same language will be used until a new forced language is chosen using this method. + +_Sofie_ currently supports three languages: +* English _(default)_ `en` +* Norwegian bokmĂĄl `nb` +* Norwegian nynorsk `nn` + +## Further Reading + +* [List of language tags](https://en.wikipedia.org/wiki/IETF_language_tag) \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/prompter.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/prompter.md new file mode 100644 index 0000000000..893e43f7af --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/prompter.md @@ -0,0 +1,189 @@ +--- +sidebar_position: 3 +--- + +# Prompter + +See [Sofie views](sofie-views.mdx#prompter-view) for how to access the prompter page. + +![Prompter screen before the first Part is taken](/img/docs/main/features/prompter-view.png) + +The prompter will display the script for the Rundown currently active in the Studio. On Air and Next parts and segments are highlighted - in red and green, respectively - to aid in navigation. In top-right corner of the screen, a Diff clock is shown, showing the difference between planned playback and what has been actually produced. This allows the host to know how far behind/ahead they are in regards to planned execution. + +![Indicators for the On Air and Next part shown underneath the Diff clock](/img/docs/main/features/prompter-view-indicators.png) + +If the user scrolls the prompter ahead or behind the On Air part, helpful indicators will be shown in the right-hand side of the screen. If the On Air or Next part's script is above the current viewport, arrows pointing up will be shown. If the On Air part's script is below the current viewport, a single arrow pointing down will be shown. + +## Customize looks + +The prompter UI can be configured using query parameters: + +| Query parameter | Type | Description | Default | +| :-------------- | :----- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------ | +| `mirror` | 0 / 1 | Mirror the display horizontally | `0` | +| `mirrorv` | 0 / 1 | Mirror the display vertically | `0` | +| `fontsize` | number | Set a custom font size of the text. 20 will fit in 5 lines of text, 14 will fit 7 lines etc.. | `14` | +| `marker` | string | Set position of the read-marker. Possible values: "center", "top", "bottom", "hide" | `hide` | +| `margin` | number | Set margin of screen \(used on monitors with overscan\), in %. | `0` | +| `showmarker` | 0 / 1 | If the marker is not set to "hide", control if the marker is hidden or not | `1` | +| `showscroll` | 0 / 1 | Whether the scroll bar should be shown | `1` | +| `followtake` | 0 / 1 | Whether the prompter should automatically scroll to current segment when the operator TAKE:s it | `1` | +| `showoverunder` | 0 / 1 | The timer in the top-right of the prompter, showing the overtime/undertime of the current show. | `1` | +| `debug` | 0 / 1 | Whether to display a debug box showing controller input values and the calculated speed the prompter is currently scrolling at. Used to tweak speedMaps and ranges. | `0` | + +Example: [http://127.0.0.1/prompter/studio0/?mode=mouse&followtake=0&fontsize=20](http://127.0.0.1/prompter/studio0/?mode=mouse&followtake=0&fontsize=20) + +## Controlling the prompter + +The prompter can be controlled by different types of controllers. The control mode is set by a query parameter, like so: `?mode=mouse`. + +| Query parameter | Description | +| :---------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Default | Controlled by both mouse and keyboard | +| `?mode=mouse` | Controlled by mouse only. [See configuration details](prompter.md#control-using-mouse-scroll-wheel) | +| `?mode=keyboard` | Controlled by keyboard only. [See configuration details](prompter.md#control-using-keyboard) | +| `?mode=shuttlekeyboard` | Controlled by a Contour Design ShuttleXpress, X-keys Jog and Shuttle or any compatible, configured as keyboard-ish device. [See configuration details](prompter.md#control-using-contour-shuttlexpress-or-x-keys) | +| `?mode=pedal` | Controlled by any MIDI device outputting note values between 0 - 127 of CC notes on channel 8. Analogue Expression pedals work well with TRS-USB midi-converters. [See configuration details](prompter.md#control-using-midi-input-mode-pedal) | +| `?mode=joycon` | Controlled by Nintendo Switch Joycon, using the HTML5 GamePad API. [See configuration details](prompter.md#control-using-nintendo-joycon-gamepad) | + +#### Control using mouse \(scroll wheel\) + +The prompter can be controlled in multiple ways when using the scroll wheel: + +| Query parameter | Description | +| :-------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `?controlmode=normal` | Scrolling of the mouse works as "normal scrolling" | +| `?controlmode=speed` | Scrolling of the mouse changes the speed of scolling. Left-click to toggle, right-click to rewind | +| `?controlmode=smoothscroll` | Scrolling the mouse wheel starts continous scrolling. Small speed adjustments can then be made by nudging the scroll wheel. Stop the scrolling by making a "larger scroll" on the wheel. | + +has several operating modes, described further below. All modes are intended to be controlled by a computer mouse or similar, such as a presenter tool. + +#### Control using keyboard + +Keyboard control is intended to be used when having a "keyboard"-device, such as a presenter tool. + +| Scroll up | Scroll down | +| :----------- | :------------ | +| `Arrow Up` | `Arrow Down` | +| `Arrow Left` | `Arrow Right` | +| `Page Up` | `Page Down` | +| | `Space` | + +#### Control using Contour ShuttleXpress or X-keys \(_?mode=shuttlekeyboard_\) + +This mode is intended to be used when having a Contour ShuttleXpress or X-keys device, configured to work as a keyboard device. These devices have jog/shuttle wheels, and their software/firmware allow them to map scroll movement to keystrokes from any key-combination. Since we only listen for key combinations, it effectively means that any device outputing keystrokes will work in this mode. + +| Query parameter | Type | Description | Default | +| :----------------- | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------- | +| `shuttle_speedMap` | Array of numbers | Speeds to scroll by \(px. pr. frame - approx 60fps\) when scrolling forwards. The beginning of the forwards-range maps to the first number in this array, and the end of the forwards-range map to the end of this array. All values in between are being interpolated using a spline curve. | `0, 1, 2, 3, 5, 7, 9, 30]` | + +| Key combination | Function | +| :--------------------------------------------------------- | :------------------------------------- | +| `Ctrl` `Alt` `F1` ... `Ctrl` `Alt` `F7` | Set speed to +1 ... +7 \(Scroll down\) | +| `Ctrl` `Shift` `Alt` `F1` ... `Ctrl` `Shift` `Alt` `F7` | Set speed to -1 ... -7 \(Scroll up\) | +| `Ctrl` `Alt` `+` | Increase speed | +| `Ctrl` `Alt` `-` | Decrease speed | +| `Ctrl` `Alt` `Shift` `F8`, `Ctrl` `Alt` `Shift` `PageDown` | Jump to next Segment and stop | +| `Ctrl` `Alt` `Shift` `F9`, `Ctrl` `Alt` `Shift` `PageUp` | Jump to previous Segment and stop | +| `Ctrl` `Alt` `Shift` `F10` | Jump to top of Script and stop | +| `Ctrl` `Alt` `Shift` `F11` | Jump to Live and stop | +| `Ctrl` `Alt` `Shift` `F12` | Jump to next Segment and stop | + +Configuration files that can be used in their respective driver software: + +- [Contour ShuttleXpress](https://github.com/nrkno/sofie-core/blob/release26/resources/prompter_layout_shuttlexpress.pref) +- [X-keys](https://github.com/nrkno/sofie-core/blob/release26/resources/prompter_layout_xkeys.mw3) + +#### + +#### Control using midi input \(_?mode=pedal_\) + +This mode listens to MIDI CC-notes on channel 8, expecting a linear range like i.e. 0-127. Sutiable for use with expression pedals, but any MIDI controller can be used. The mode picks the first connected MIDI device, and supports hot-swapping \(you can remove and add the device without refreshing the browser\). + +Web-Midi requires the web page to be served over HTTPS, or that the Chrome flag `unsafely-treat-insecure-origin-as-secure` is set. + +If you want to use traditional analogue pedals with 5 volt TRS connection, a converter such as the _Beat Bars EX2M_ will work well. + +| Query parameter | Type | Description | Default | +| :---------------------- | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------- | +| `pedal_speedMap` | Array of numbers | Speeds to scroll by \(px. pr. frame - approx 60fps\) when scrolling forwards. The beginning of the forwards-range maps to the first number in this array, and the end of the forwards-range map to the end of this array. All values in between are being interpolated using a spline curve. | `[1, 2, 3, 4, 5, 7, 9, 12, 17, 19, 30]` | +| `pedal_reverseSpeedMap` | Array of numbers | Same as `pedal_speedMap` but for the backwards range. | `[10, 30, 50]` | +| `pedal_rangeRevMin` | number | The end of the backwards-range, full speed backwards. | `0` | +| `pedal_rangeNeutralMin` | number | The beginning of the backwards-range. | `35` | +| `pedal_rangeNeutralMax` | number | The minimum input to run forward, the start of the forward-range \(min speed\). This is also the end of any "deadband" you want filter out before starting moving forwards. | `80` | +| `pedal_rangeFwdMax` | number | The maximum input, the end of the forward-range \(max speed\) | `127` | + +- `pedal_rangeNeutralMin` has to be greater than `pedal_rangeRevMin` +- `pedal_rangeNeutralMax` has to be greater than `pedal_rangeNeutralMin` +- `pedal_rangeFwdMax` has to be greater than `pedal_rangeNeutralMax` + +![Yamaha FC7 mapped for both a forward \(80-127\) and backwards \(0-35\) range.](/img/docs/main/features/yamaha-fc7.jpg) + +The default values allow for both going forwards and backwards. This matches the _Yamaha FC7_ expression pedal. The default values create a forward-range from 80-127, a neutral zone from 35-80 and a reverse-range from 0-35. + +Any movement within forward range will map to the `pedal_speedMap` with interpolation between any numbers in the `pedal_speedMap`. You can turn on `?debug=1` to see how your input maps to an output. This helps during calibration. Similarly, any movement within the backwards rage maps to the `pedal_reverseSpeedMap`. + +**Calibration guide:** + +| **Symptom** | Adjustment | +| :---------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| _"I can't rest my foot without it starting to run"_ | Increase `pedal_rangeNeutralMax` | +| _"I have to push too far before it starts moving"_ | Decrease `pedal_rangeNeutralMax` | +| _"It starts out fine, but runs too fast if I push too hard"_ | Add more weight to the lower part of the `pedal_speedMap` by adding more low values early in the map, compared to the large numbers in the end. | +| _"I have to go too far back to reverse"_ | Increse `pedal_rangeNeutralMin` | +| _"As I find a good speed, it varies a bit in speed up/down even if I hold my foot still"_ | Use `?debug=1` to see what speed is calculated in the position the presenter wants to rest the foot in. Add more of that number in a sequence in the `pedal_speedMap` to flatten out the speed curve, i.e. `[1, 2, 3, 4, 4, 4, 4, 5, ...]` | + +**Note:** The default values are set up to work with the _Yamaha FC7_ expression pedal, and will probably not be good for pedals with one continuous linear range from fully released to fully depressed. A suggested configuration for such pedals \(i.e. the _Mission Engineering EP-1_\) will be like: + +| Query parameter | Suggestion | +| :---------------------- | :-------------------------------------- | +| `pedal_speedMap` | `[1, 2, 3, 4, 5, 7, 9, 12, 17, 19, 30]` | +| `pedal_reverseSpeedMap` | `-2` | +| `pedal_rangeRevMin` | `-1` | +| `pedal_rangeNeutralMin` | `0` | +| `pedal_rangeNeutralMax` | `1` | +| `pedal_rangeFwdMax` | `127` | + +#### Control using Nintendo Joycon \(_?mode=joycon_\) + +This mode uses the browsers Gamapad API and polls connected Joycons for their states on button-presses and joystick inputs. + +The Joycons can operate in 3 modes, the L-stick, the R-stick or both L+R sticks together. Reconnections and jumping between modes works, with one known limitation: **Transition from L+R to a single stick blocks all input, and requires a reconnect of the sticks you want to use.** This seems to be a bug in either the Joycons themselves or in the Gamepad API in general. + +| Query parameter | Type | Description | Default | +| :----------------------- | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------- | +| `joycon_speedMap` | Array of numbes | Speeds to scroll by \(px. pr. frame - approx 60fps\) when scrolling forwards. The beginning of the forwards-range maps to the first number in this array, and thee end of the forwards-range map to the end of this array. All values in between are being interpolated in a spline curve. | `[1, 2, 3, 4, 5, 8, 12, 30]` | +| `joycon_reverseSpeedMap` | Array of numbers | Same as `joycon_speedMap` but for the backwards range. | `[1, 2, 3, 4, 5, 8, 12, 30]` | +| `joycon_rangeRevMin` | number | The end of the backwards-range, full speed backwards. | `-1` | +| `joycon_rangeNeutralMin` | number | The beginning of the backwards-range. | `-0.25` | +| `joycon_rangeNeutralMax` | number | The minimum input to run forward, the start of the forward-range \(min speed\). This is also the end of any "deadband" you want filter out before starting moving forwards. | `0.25` | +| `joycon_rangeFwdMax` | number | The maximum input, the end of the forward-range \(max speed\) | `1` | + +- `joycon_rangeNeutralMin` has to be greater than `joycon_rangeRevMin` +- `joycon_rangeNeutralMax` has to be greater than `joycon_rangeNeutralMin` +- `joycon_rangeFwdMax` has to be greater than `joycon_rangeNeutralMax` + +![Nintendo Swith Joycons](/img/docs/main/features/nintendo-switch-joycons.jpg) + +You can turn on `?debug=1` to see how your input maps to an output. + +**Button map:** + +| **Button** | Acton | +| :--------- | :------------------------ | +| L2 / R2 | Go to the "On-air" story | +| L / R | Go to the "Next" story | +| Up / X | Go top the top | +| Left / Y | Go to the previous story | +| Right / A | Go to the following story | + +**Calibration guide:** + +| **Symptom** | Adjustment | +| :------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| _"The prompter drifts upwards when I'm not doing anything"_ | Decrease `joycon_rangeNeutralMin` | +| _"The prompter drifts downwards when I'm not doing anything"_ | Increase `joycon_rangeNeutralMax` | +| _"It starts out fine, but runs too fast if I move too far"_ | Add more weight to the lower part of the `joycon_speedMap / joycon_reverseSpeedMap` by adding more low values early in the map, compared to the large numbers in the end. | +| _"I can't reach max speed backwards"_ | Increase `joycon_rangeRevMin` | +| _"I can't reach max speed forwards"_ | Decrease `joycon_rangeFwdMax` | +| _"As I find a good speed, it varies a bit in speed up/down even if I hold my finger still"_ | Use `?debug=1` to see what speed is calculated in the position the presenter wants to rest their finger in. Add more of that number in a sequence in the `joycon_speedMap` to flatten out the speed curve, i.e. `[1, 2, 3, 4, 4, 4, 4, 5, ...]` | diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/sofie-views.mdx b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/sofie-views.mdx new file mode 100644 index 0000000000..e3d21dc9be --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/sofie-views.mdx @@ -0,0 +1,313 @@ +--- +sidebar_position: 2 +--- + +import Tabs from '@theme/Tabs' +import TabItem from '@theme/TabItem' + +# Sofie Views + +## Lobby View + +![Rundown View](/img/docs/lobby-view.png) + +All existing rundowns are listed in the _Lobby View_. + +## Rundown View + +![Rundown View](/img/docs/main/features/active-rundown-example.png) + +The _Rundown View_ is the main view that the producer is working in. + +![The Rundown view and naming conventions of components](/img/docs/main/sofie-naming-conventions.png) + +![Take Next](/img/docs/main/take-next.png) + +#### Take Point + +The Take point is currently playing [Part](#part) in the rundown, indicated by the "On Air" line in the GUI. +What's played on air is calculated from the timeline objects in the Pieces in the currently playing part. + +The Pieces inside of a Part determines what's going to happen, the could be indicating things like VT:s, cut to cameras, graphics, or what script the host is going to read. + +:::info +You can TAKE the next part by pressing _F12_ or the _Numpad Enter_ key. +::: + +#### Next Point + +The Next point is the next queued Part in the rundown. When the user clicks _Take_, the Next Part becomes the currently playing part, and the Next point is also moved. + +:::info +Change the Next point by right-clicking in the GUI, or by pressing \(Shift +\) F9 & F10. +::: + +#### Freeze-frame Countdown + +![Part is 1 second heavy, LiveSpeak piece has 7 seconds of playback until it freezes](/img/docs/main/freeze-frame-countdown.png) + +If a Piece has more or less content than the Part's expected duration allows, an additional counter with a Snowflake icon will be displayed, attached to the On Air line, counting down to the moment when content from that Piece will freeze-frame at the last frame. The time span in which the content from the Piece will be visible on the output, but will be frozen, is displayed with an overlay of icicles. + +#### Lookahead + +Elements in the [Next point](#next-point) \(or beyond\) might be pre-loaded or "put on preview", depending on the blueprints and playout devices used. This feature is called "Lookahead". + +### Storyboard Mode + +In the top-right corner of the Segment, there's a button controlling the display style of a given Segment. The default display style of a Segment can be indicated by the [Blueprints](../concepts-and-architecture.md#blueprints), but the User can switch to a different mode at any time. You can also change the display mode of all Segments at once, using a button in the bottom-right corner of the Rundown View. + +![Storyboard Mode](/img/docs/main/storyboard.png) + +The **_Storyboard_** mode is an alternative to the default **_Timeline_** mode. In Storyboard mode, the accurate placement in time of each Piece is not visualized, so that more Parts can be visualized at once in a single row. This can be particularly useful in Shows without very strict timing planning or where timing is not driven by the User, but rather some external factor; or in Shows where very long Parts are joined with very short ones: sports, events and debates. This mode also does not visualize the history of the playback: rather, it only shows what is currently On Air or is planned to go On Air. + +Storyboard mode selects a "main" Piece of the Part, using the same logic as the [Presenter View](#presenter-view), and presents it with a larger, hover-scrub-enabled Piece for easy preview. The countdown to freeze-frame is displayed in the top-right hand corner of the Thumbnail, once less than 10 seconds remain to freeze-frame. The Transition Piece is displayed on top of the thumbnail. Other Pieces are placed below the thumbnail, stacked in order of playback. After a Piece goes off-air, it will dissapear from the view. + +If no more Parts can be displayed in a given Segment, they are stacked in order on the right side of the Segment. The User can scroll through thse Parts by click-and-dragging the Storyboard area, or using the mouse wheel - `Alt`+Wheel, if only a vertical wheel is present in the mouse. + +### List View Mode + +Another mode available to display a Segment is the List View. In this mode, each _Part_ and it's contents are being displayed as a mini-timeline and it's width is normalized to fit the screen, unless it's shorter than 30 seconds, in which case it will be scaled down accordingly. + +![List View Mode](/img/docs/main/list_view.png) + +In this mode, the focus is on the "main" Piece of the Part. Additional _Lower-Third_ content that is not spanning the entire Part (is not infinite) will be displayed on top of the main Piece. All other content can be displayed to the right of the mini-timeline as a set of indicators, one per every Layer. Clicking on those indicators will show a pop-up with the Pieces so that they can be investigated using _hover-scrub_. Indicators can be also shown for Ad-Libs assigned to a Part, for easier discovery by the User. Which Layers should be shown in the columns can be decided in the [Settings â—Ź Layers](../configuration/settings-view.md#show-style) area. A special, larger indicator is reserved for the Script piece, which can be useful to display so-called _out-words_. + +If a Part has an _in-transition_ Piece, it will be displayed to the left of the Part's Take Point. + +This view is designed to be used in productions that are mixing pre-planned and timed segments with more free-flowing production or mixing short live in-camera links with longer pre-produced clips, while trying to keep as much of the show in the viewport as possible, at the expense of hiding some of the content from the User and the _duration_ of the Part on screen having no bearing on it's _width_. This mode also allows Sofie to visualize content _beyond_ the planned duration of a Part. + +:::info +The Segment header area also shows the expected (planned) durations for all the Parts and will also show which Parts are sharing timing in a timing group using a *⌊* symbol in the place of a counter. +::: + +All user interactions work in the Storyboard and List View mode the same as in Timeline mode: Takes, AdLibs, Holds and moving the [Next Point](#next-point) around the Rundown. + +### Segment Header Countdowns + +![Each Segment has two clocks - the Segment Time Budget and a Segment Countdown](/img/docs/main/segment-budget-and-countdown.png) + + + +Clock on the left is an indicator of how much time has been spent playing Parts from that Segment in relation to how much time was planned for Parts in that Segment. If more time was spent playing than was planned for, this clock will turn red, there will be a **+** sign in front of it and will begin counting upwards. + + + +Clock on the right is a countdown to the beginning of a given segment. This takes into account unplayed time in the On Air Part and all unplayed Parts between the On Air Part and a given Segment. If there are no unplayed Parts between the On Air Part and the Segment, this counter will disappear. + + + +In the illustration above, the first Segment \(_Ny Sak_\) has been playing for 4 minutes and 25 seconds longer than it was planned for. The second segment \(_Direkte Strømstad\)_ is planned to play for 4 minutes and 40 seconds. There are 5 minutes and 46 seconds worth of content between the current On Air line \(which is in the first Segment\) and the second Segment. + +If you click on the Segment header countdowns, you can switch the _Segment Countdown_ to a _Segment OnAir Clock_ where this will show the time-of-day when a given Segment is expected to air. + +![Each Segment has two clocks - the Segment Time Budget and a Segment Countdown](/img/docs/main/features/segment-header-2.png) + +### Rundown Dividers + +When using a workflow and blueprints that combine multiple NRCS Rundowns into a single Sofie Rundown \(such as when using the "Ready To Air" functionality in AP ENPS\), information about these individual NRCS Rundowns will be inserted into the Rundown View at the point where each of these incoming Rundowns start. + +![Rundown divider between two NRCS Rundowns in a "Ready To Air" Rundown](/img/docs/main/rundown-divider.png) + +For reference, these headers show the Name, Planned Start and Planned Duration of the individual NRCS Rundown. + +### Shelf + +The shelf contains lists of AdLibs that can be played out. + +![Shelf](/img/docs/main/shelf.png) + +:::info +The Shelf can be opened by clicking the handle at the bottom of the screen, or by pressing the TAB key +::: + +### Shelf Layouts + +The _Rundown View_ and the _Detached Shelf View_ UI can have multiple concurrent layouts for any given Show Style. The automatic selection mechanism works as follows: + +1. select the first layout of the `RUNDOWN_LAYOUT` type, +2. select the first layout of any type, +3. use the default layout \(no additional filters\), in the style of `RUNDOWN_LAYOUT`. + +To use a specific layout in these views, you can use the `?layout=...` query string, providing either the ID of the layout or a part of the name. This string will then be mached against all available layouts for the Show Style, and the first matching will be selected. For example, for a layout called `Stream Deck layout`, to open the currently active rundown's Detached Shelf use: + +`http://localhost:3000/activeRundown/studio0/shelf?layout=Stream` + +The Detached Shelf view with a custom `DASHBOARD_LAYOUT` allows displaying the Shelf on an auxiliary touch screen, tablet or a Stream Deck device. A specialized Stream Deck view will be used if the view is opened on a device with hardware characteristics matching a Stream Deck device. + +The shelf also contains additional elements, not controlled by the Rundown View Layout. These include Buckets and the Inspector. If needed, these components can be displayed or hidden using additional url arguments: + +| Query parameter | Description | +| :---------------------------------- | :------------------------------------------------------------------------ | +| Default | Display the rundown layout \(as selected\), all buckets and the inspector | +| `?display=layout,buckets,inspector` | A comma-separated list of features to be displayed in the shelf | +| `?buckets=0,1,...` | A comma-separated list of buckets to be displayed | + +- `display`: Available values are: `layout` \(for displaying the Rundown Layout\), `buckets` \(for displaying the Buckets\) and `inspector` \(for displaying the Inspector\). +- `buckets`: The buckets can be specified as base-0 indices of the buckets as seen by the user. This means that `?buckets=1` will display the second bucket as seen by the user when not filtering the buckets. This allows the user to decide which bucket is displayed on a secondary attached screen simply by reordering the buckets on their main view. + +_Note: the Inspector is limited in scope to a particular browser window/screen, so do not expect the contents of the inspector to sync across multiple screens._ + +For the purpose of running the system in a studio environment, there are some additional views that can be used for various purposes: + +### Sidebar Panel + +#### Switchboard + +![Switchboard](/img/docs/main/switchboard.png) + +The Switchboard allows the producer to turn automation _On_ and _Off_ for sets of devices, as well as re-route automation control between devices - both with an active rundown and when no rundown is active in a [Studio](../concepts-and-architecture.md#system-organization-studio-and-show-style). + +The Switchboard panel can be accessed from the Rundown View's right-hand Toolbar, by clicking on the Switchboard button, next to the Support panel button. + +:::info +Technically, the switchboard activates and deactivates Route Sets. The Route Sets are grouped by Exclusivity Group. If an Exclusivity Group contains exactly two elements with the `ACTIVATE_ONLY` mode, the Route Sets will be displayed on either side of the switch. Otherwise, they will be displayed separately in a list next to an _Off_ position. See also [Settings â—Ź Route sets](../configuration/settings-view#route-sets). +::: + +## Prompter View + +`/prompter/:studioId` + +![Prompter View](/img/docs/main/features/prompter-example.png) + +A fullscreen page which displays the prompter text for the currently active rundown. The prompter can be controlled and configured in various ways, see more at the [Prompter](prompter.md) documentation. If no Rundown is active in a given studio, the [Screensaver](sofie-views.mdx#screensaver) will be displayed. + +## Presenter View + +`/countdowns/:studioId/presenter` + +![Presenter View](/img/docs/main/features/presenter-screen-example.png) + +A fullscreen page, intended to be shown to the studio presenter. It displays countdown timers for the current and next items in the rundown. If no Rundown is active in a given studio, the [Screensaver](sofie-views.mdx#screensaver) will be shown. + +### Presenter View Overlay + +`/countdowns/:studioId/overlay` + +![Presenter View Overlay](/img/docs/main/features/presenter-screen-overlay-example.png) + +A fullscreen view with transparent background, intended to be shown to the studio presenter as an overlay on top of the produced PGM signal. It displays a reduced amount of the information from the regular [Presenter screen](sofie-views.mdx#presenter-view): the countdown to the end of the current Part, a summary preview \(type and name\) of the next item in the Rundown and the current time of day. If no Rundown is active it will show the name of the Studio. + +## Camera Position View + +`/countdowns/:studioId/camera` + +![Camera Position View](/img/docs/main/features/camera-view.jpg) + +A fullscreen view designed specifically for use on mobile devices or extra screens displaying a summary of the currently active Rundown, filtered for Parts containing Pieces matching particular Source Layers and Studio Labels. + +The Pieces are displayed as a Timeline, with the Pieces moving right-to-left as time progresses, and Parts being displayed from the current one being played up till the end of the Rundown. The closest (not necessarily _Next_) Part has a countdown timer in the top-right corner showing when it's expected to be Live. Each Part also has a Duration counter on the bottom-right. + +This view can be configured using query parameters: + +| Query parameter | Type | Description | Default | +| :-------------- | :--- | :---------- | :------ | +| `sourceLayerIds` | string | A comma-separated list of Source Layer IDs to be considered for display | _(show all)_ | +| `studioLabels` | string | A comma-separated list of Studio Labels (Piece `.content.studioLabel` values) to be considered for display | _(show all)_ | +| `fullscreen` | 0 / 1 | Should the view become fullscreen on the device on first user interaction | 0 | + +Example: [http://127.0.0.1/countdowns/studio0/camera?sourceLayerIds=camera0,dve0&studioLabels=1,KAM%201,K1,KAM1&fullscreen=1](http://127.0.0.1/countdowns/studio0/camera?sourceLayerIds=camera0,dve0&studioLabels=1,KAM%201,K1,KAM1&fullscreen=1) + +## Active Rundown View + +`/activeRundown/:studioId` + +![Active Rundown View](/img/docs/main/features/active-rundown-example.png) + +A page which automatically displays the currently active rundown. Can be useful for the producer to have on a secondary screen. + +## Active Rundown – Shelf + +`/activeRundown/:studioId/shelf` + +![Active Rundown Shelf](/img/docs/main/features/active-rundown-shelf-example.png) + +A view which automatically displays the currently active rundown, and shows the Shelf in full screen. Can be useful for the producer to have on a secondary screen. + +A shelf layout can be selected by modifying the query string, see [Shelf Layouts](#shelf-layouts). + +## Specific Rundown – Shelf + +`/rundown/:rundownId/shelf` + +Displays the shelf in fullscreen for a rundown + +## Screensaver + +When big screen displays \(like Prompter and the Presenter screen\) do not have any meaningful content to show, an animated screensaver showing the current time and the next planned show will be displayed. If no Rundown is upcoming, the Studio name will be displayed. + +![A screensaver showing the next scheduled show](/img/docs/main/features/next-scheduled-show-example.png) + +## System Status + +:::caution +Documentation for this feature is yet to be written. +::: + +System and devices statuses are displayed here. + +:::info +An API endpoint for the system status is also available under the URL `/health` +::: + +## Media Status View + +:::caution +Documentation for this feature is yet to be written. +::: + +This page displays media transfer statuses. + +## Message Queue View + +:::caution +Documentation for this feature is yet to be written. +::: + +_Sofie Core_ can send messages to external systems \(such as metadata, as-run-logs\) while on air. + +These messages are retained for a period of time, and can be reviewed in this list. + +Messages that was not successfully sent can be inspected and re-sent here. + +## User Log View + +The user activity log contains a list of the user-actions that users have previously done. This is used in troubleshooting issues on-air. + +![User Log](/img/docs/main/features/user-log.png) + +### Columns, explained + +#### Execution time + +The execution time column displays **coreDuration** + **gatewayDuration** \(**timelineResolveDuration**\)": + +- **coreDuration** : The time it took for Core to execute the command \(ie start-of-command đź ş stored-result-into-database\) +- **gatewayDuration** : The time it took for Playout Gateway to execute the timeline \(ie stored-result-into-database đź ş timeline-resolved đź ş callback-to-core\) +- **timelineResolveDuration**: The duration it took in TSR \(in Playout Gateway\) to resolve the timeline + +Important to note is that **gatewayDuration** begins at the exact moment **coreDuration** ends. +So **coreDuration + gatewayDuration** is the full time it took from beginning-of-user-action to the timeline-resolved \(plus a little extra for the final callback for reporting the measurement\). + +#### Action + +Describes what action the user did; e g pressed a key, clicked a button, or selected a meny item. + +#### Method + +The internal name in _Sofie Core_ of what function was called + +#### Status + +The result of the operation. "Success" or an error message. + +## Evaluations + +When a broadcast is done, users can input feedback about how the show went in an evaluation form. + +:::info +Evaluations can be configured to be sent to Slack, by setting the "Slack Webhook URL" in the [Settings View](../configuration/settings-view.md) under _Studio_. +::: + +## Settings View + +The [Settings View](../configuration/settings-view.md) is only available to users with the [Access Level](access-levels.md) set correctly. diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/system-health.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/system-health.md new file mode 100644 index 0000000000..11ab7046b4 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/features/system-health.md @@ -0,0 +1,27 @@ +--- +sidebar_position: 11 +--- + +# System Health + +## Legacy healthcheck + +There is a legacy `/health` endpoint used by NRK systems. Its use is being phased out and will eventually be replaced by the new prometheus endpoint. + +## Prometheus + +From version 1.49, there is a prometheus `/metrics` endpoint exposed from Sofie. The metrics exposed from here will increase over time as we find more data to collect. + +Because Sofie is comprised of multiple worker-threads, each metric has a `threadName` label indicitating which it is from. In many cases this field will not matter, but it is useful for the default process metrics, and if your installation has multiple studios defined. + +Each thread exposes some default nodejs process metrics. These are defined by the [`prom-client`](https://github.com/siimon/prom-client#default-metrics) library we are using, and are best described there. + +The current Sofie metrics exposed are: + +| name | type | description | +| ------------------------------------------ | ------- | ------------------------------------------------------------------ | +| sofie_meteor_ddp_connections_total | Gauge | Number of open ddp connections | +| sofie_meteor_publication_subscribers_total | Gauge | Number of subscribers on a Meteor publication (ignoring arguments) | +| sofie_meteor_jobqueue_queue_total | Counter | Number of jobs put into each worker job queues | +| sofie_meteor_jobqueue_success | Counter | Number of successful jobs from each worker | +| sofie_meteor_jobqueue_queue_errors | Counter | Number of failed jobs from each worker | diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/further-reading.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/further-reading.md new file mode 100644 index 0000000000..caea59f4f2 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/further-reading.md @@ -0,0 +1,59 @@ +--- +description: This guide has a lot of links. Here they are all listed by section. +--- + +# Further Reading + +## Getting Started + +- [Sofie's Concepts & Architecture](concepts-and-architecture.md) +- [Gateways](concepts-and-architecture.md#gateways) +- [Blueprints](concepts-and-architecture.md#blueprints) + +- Ask questions in the [Sofie Slack Channel](https://join.slack.com/t/sofietv/shared_invite/enQtNTk2Mzc3MTQ1NzAzLTJkZjMyMDg3OGM0YWU3MmU4YzBhZDAyZWI1YmJmNmRiYWQ1OTZjYTkzOTkzMTA2YTE1YjgxMmVkM2U1OGZlNWI) + +## Installation & Setup + +### Installing Sofie Core + +- [Windows install for Docker](https://hub.docker.com/editions/community/docker-ce-desktop-windows) +- [Linux install instructions for Docker](https://docs.docker.com/install/linux/docker-ce/ubuntu/) +- [Linux install instructions for Docker Compose](https://www.digitalocean.com/community/tutorials/how-to-install-docker-compose-on-ubuntu-18-04) +- [Sofie Core Docker File Download](https://firebasestorage.googleapis.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LWRCgfY_-kYo9iX6UNy%2F-Lo5eWjgoVlRRDeFzLuO%2F-Lo5fLSSyM1eO6OXScew%2Fdocker-compose.yaml?alt=media&token=fc2fbe79-365c-4817-b270-e507c6a6e3c6) + +### Installing a Gateway + +#### Ingest Gateways and NRCS + +- [MOS Protocol Overview & Documentation](http://mosprotocol.com/) +- Information about ENPS on [The Associated Press' Website](https://www.ap.org/enps/support) +- Information about iNews: [Avid's Website](https://www.avid.com/products/inews/how-to-buy) + +**Google Spreadsheet Gateway** + +- [Demo Blueprints](https://github.com/SuperFlyTV/sofie-demo-blueprints/releases) on GitHub's website. +- [Example Rundown](https://docs.google.com/spreadsheets/d/1iyegRv5MxYYtlVu8uEEMkBYXsLL-71PAMrNW0ZfWRUw/edit?usp=sharing) provided by Sofie. +- [Google Sheets API](https://console.developers.google.com/apis/library/sheets.googleapis.com?) on the Google Developer website. + +### Additional Software & Hardware + +#### Installing CasparCG Server for Sofie + +- NRK's version of [CasparCG Server](https://github.com/nrkno/sofie-casparcg-server/releases) on GitHub. +- [Media Scanner](https://github.com/nrkno/sofie-casparcg-launcher/releases) on GitHub. +- [CasparCG Launcher](https://github.com/nrkno/sofie-casparcg-launcher) on GitHub. +- [Microsoft Visual C++ 2015 Redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=52685) on Microsoft's website. +- [Blackmagic Design's DeckLink Cards](https://www.blackmagicdesign.com/products/decklink/models) on Blackmagic Design's website. Check the [DeckLink cards](installation/installing-connections-and-additional-hardware/casparcg-server-installation.md#decklink-cards) section for compatibility. +- [Installing a DeckLink Card](https://documents.blackmagicdesign.com/UserManuals/DesktopVideoManual.pdf) as a PDF. +- [Blackmagic Design 'Desktop Video' Driver Download](https://www.blackmagicdesign.com/support/family/capture-and-playback) on Blackmagic Design's website. +- [CasparCG Server Configuration Validator](https://casparcg.net/validator/) + +**Additional Resources** + +- Viz graphics through MSE, info on the [Vizrt](https://www.vizrt.com/) website. +- Information about the [Blackmagic Design's HyperDeck](https://www.blackmagicdesign.com/products/hyperdeckstudio) + +## FAQ, Progress, and Issues + +- [MIT Licence](https://opensource.org/licenses/MIT) +- [Releases and Issues on GitHub](https://github.com/nrkno/Sofie-TV-automation/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3ARelease) diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/_category_.json b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/_category_.json new file mode 100644 index 0000000000..2f3c7f2a9f --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Installation", + "position": 3 +} \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/initial-sofie-core-setup.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/initial-sofie-core-setup.md new file mode 100644 index 0000000000..c0672b3e55 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/initial-sofie-core-setup.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +--- + +# Initial Sofie Core Setup + +#### Prerequisites + +* [Installed and running _Sofie Core_](installing-sofie-server-core.md) + +Once _Sofie Core_ has been installed and is running you can begin setting it up. The first step is to navigate to the _Settings page_. Please review the [Sofie Access Level](../features/access-levels.md) page for assistance getting there. + +To upgrade to a newer version or installation of new blueprints, Sofie needs to run its "Upgrade database" procedure to migrate data and pre-fill various settings. You can do this by clicking the _Upgrade Database_ button in the menu. + +![Update Database Section of the Settings Page](/img/docs/getting-started/settings-page-full-update-db-r47.png) + +Fill in the form as prompted and continue by clicking _Run Migrations Procedure_. Sometimes you will need to go through multiple steps before the upgrade is finished. + +Next, you will need to add some [Blueprints](installing-blueprints.md) and add [Gateways](installing-a-gateway/intro.md) to allow _Sofie_ to interpret rundown data and then play out things. + +![Initial Studio Settings Page](/img/docs/getting-started/settings-page-initial-studio.png) + +Next, you will need to add some [Blueprints](installing-blueprints) and add [Gateways](installing-a-gateway/intro) to allow _Sofie_ to interpret rundown data and then play out things. diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/_category_.json b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/_category_.json new file mode 100644 index 0000000000..7fa55d484d --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Installing a Gateway", + "position": 5 +} \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/intro.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/intro.md new file mode 100644 index 0000000000..03bc8a5339 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/intro.md @@ -0,0 +1,25 @@ +--- +sidebar_label: Introduction +sidebar_position: 1 +--- +# Introduction: Installing a Gateway + +#### Prerequisites + +* [Installed and running Sofie Core](../installing-sofie-server-core.md) + +The _Sofie Core_ is the primary application for managing the broadcast, but it doesn't play anything out on it's own. A Gateway will establish the connection from _Sofie Core_ to other pieces of hardware or remote software. A basic setup may include the [Spreadsheet Gateway](rundown-or-newsroom-system-connection/installing-sofie-with-google-spreadsheet-support.md) which will ingest a rundown from Google Sheets then, use the [Playout Gateway](playout-gateway.md) send commands to a CasparCG Server graphics playout, an ATEM vision mixer, and / or the [Sisyfos audio controller](https://github.com/olzzon/sisyfos-audio-controller). + +Installing a gateway is a two part process. To begin, you will [add the required Blueprints](../installing-blueprints.md), or mini plug-in programs, to _Sofie Core_ so it can manipulate the data from the Gateway. Then you will install the Gateway itself. Each Gateway follows a similar installation pattern but, each one does differ slightly. The links below will help you navigate to the correct Gateway for the piece of hardware / software you are using. + +### Rundown & Newsroom Gateways + +* [Google Spreadsheet Gateway](rundown-or-newsroom-system-connection/installing-sofie-with-google-spreadsheet-support.md) +* [iNEWS Gateway](rundown-or-newsroom-system-connection/inews-gateway.md) +* [MOS Gateway](rundown-or-newsroom-system-connection/mos-gateway.md) + +### Playout & Media Manager Gateways + +* [Playout Gateway](playout-gateway.md) +* [Media Manager](../media-manager.md) + diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/playout-gateway.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/playout-gateway.md new file mode 100644 index 0000000000..0fd5f47626 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/playout-gateway.md @@ -0,0 +1,6 @@ +--- +sidebar_position: 3 +--- +# Playout Gateway + +The _Playout Gateway_ handles interacting external pieces of hardware or software by sending commands that will playout rundown content. This gateway used to be a separate installation but it has since been moved into the main _Sofie Core_ component. diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/_category_.json b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/_category_.json new file mode 100644 index 0000000000..b4c4ffc34d --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Rundown or Newsroom System Connection", + "position": 4 +} \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/inews-gateway.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/inews-gateway.md new file mode 100644 index 0000000000..48659251a6 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/inews-gateway.md @@ -0,0 +1,12 @@ +# iNEWS Gateway + +The iNEWS Gateway communicates with an iNEWS system to ingest and remain in sync with a rundown. + +### Installing iNEWS for Sofie + +The iNEWS Gateway allows you to create rundowns from within iNEWS and sync them with the _Sofie Core_. The rundowns will update in real time and any changes made will be seen from within your Playout Timeline. + +The setup for the iNEWS Gateway is already in the Docker Compose file you downloaded earlier. Remove the _\#_ symbol from the start of the line labeled `image: tv2/inews-ftp-gateway:develop` and add a _\#_ to the other ingest gateway that was being used. + +Although the iNEWS Gateway is available free of charge, an iNEWS license is not. Visit [Avid's website](https://www.avid.com/products/inews/how-to-buy) to find an iNEWS reseller that handles your geographic area. + diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/installing-sofie-with-google-spreadsheet-support.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/installing-sofie-with-google-spreadsheet-support.md new file mode 100644 index 0000000000..8cdd2ed637 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/installing-sofie-with-google-spreadsheet-support.md @@ -0,0 +1,46 @@ +# Google Spreadsheet Gateway + +The Spreadsheet Gateway is an application for piping data between Sofie Core and Spreadsheets on Google Drive. + +### Example Blueprints for Spreadsheet Gateway + +To begin with, you will need to install a set of Blueprints that can handle the data being sent from the _Gateway_ to _Sofie Core_. Download the `demo-blueprints-r*.zip` file containing the blueprints you need from the [Demo Blueprints GitHub Repository](https://github.com/SuperFlyTV/sofie-demo-blueprints/releases). It is recommended to choose the newest release but, an older _Sofie Core_ version may require a different Blueprint version. The _Rundown page_ will warn you about any issue and display the desired versions. + +Instructions on how to install any Blueprint can be found in the [Installing Blueprints](../../installing-blueprints.md) section from earlier. + +### Spreadsheet Gateway Configuration + +If you are using the Docker version of Sofie, then the Spreadsheet Gateway will come preinstalled. For those who are not, please follow the [instructions listed on the GitHub page](https://github.com/SuperFlyTV/spreadsheet-gateway) labeled _Installation \(for developers\)._ + +Once the Gateway has been installed, you can navigate to the _Settings page_ and check the newly added Gateway is listed as _Spreadsheet Gateway_ under the _Devices section_. + +Before you select the Device, you want to add it to the current _Studio_ you are using. Select your current Studio from the menu and navigate to the _Attached Devices_ option. Click the _+_ icon and select the Spreadsheet Gateway. + +Now you can select the _Device_ from the _Devices menu_ and click the link provided to enable your Google Drive API to send files to the _Sofie Core_. The page that opens will look similar to the image below. + +![Nodejs Quickstart page](/img/docs/installation/installing-a-gateway/rundown-or-newsroom-system-connection/nodejs-quickstart.png) +xx +Make sure to follow the steps in **Create a project and enable the API** and enable the **Google Drive API** as well as the **Google Sheets API**. Your "APIs and services" Dashboard should now look as follows: + +![APIs and Services Dashboard](/img/docs/installation/installing-a-gateway/rundown-or-newsroom-system-connection/apis-and-services-dashboard.png) + +Now follow the steps in **Create credentials** and make sure to create an **OAuth Client ID** for a **Desktop App** and download the credentials file. + +![Create Credentials page](/img/docs/installation/installing-a-gateway/rundown-or-newsroom-system-connection/create-credentials.png) + +Use the button to download the configuration to a file and navigate back to _Sofie Core's Settings page_. Select the Spreadsheet Gateway, then click the _Browse_ button and upload the configuration file you just downloaded. A new link will appear to confirm access to your google drive account. Select the link and in the new window, select the Google account you would like to use. Currently, the Sofie Core Application is not verified with Google so you will need to acknowledge this and proceed passed the unverified page. Click the _Advanced_ button and then click _Go to QuickStart \( Unsafe \)_. + +After navigating through the prompts you are presented with your verification code. Copy this code into the input field on the _Settings page_ and the field should be removed. A message confirming the access token was saved will appear. + +You can now navigate to your Google Drive account and create a new folder for your rundowns. It is important that this folder has a unique name. Next, navigate back to _Sofie Core's Settings page_ and add the folder name to the appropriate input. + +The indicator should now read _Good, Watching folder 'Folder Name Here'_. Now you just need an example rundown.[ Navigate to this Google Sheets file](https://docs.google.com/spreadsheets/d/1iyegRv5MxYYtlVu8uEEMkBYXsLL-71PAMrNW0ZfWRUw/edit?usp=sharing) and select the _File_ menu and then select _Make a copy_. In the popup window, select _My Drive_ and then navigate to and select the rundowns folder you created earlier. + +At this point, one of two things will happen. If you have the Google Sheets API enabled, this is different from the Google Drive API you enabled earlier, then the Rundown you just copied will appear in the Rundown page and is accessible. The other outcome is the Spreadsheet Gateway status reads _Unknown, Initializing..._ which most likely means you need to enable the Google Sheets API. Navigate to the[ Google Sheets API Dashboard with this link](https://console.developers.google.com/apis/library/sheets.googleapis.com?) and click the _Enable_ button. Navigate back to _Sofie's Settings page_ and restart the Spreadsheet Gateway. The status should now read, _Good, Watching folder 'Folder Name Here'_ and the rundown will appear in the _Rundown page_. + +### Further Reading + +- [Demo Blueprints](https://github.com/SuperFlyTV/sofie-demo-blueprints/) GitHub Page for Developers +- [Example Rundown](https://docs.google.com/spreadsheets/d/1iyegRv5MxYYtlVu8uEEMkBYXsLL-71PAMrNW0ZfWRUw/edit?usp=sharing) provided by Sofie. +- [Google Sheets API](https://console.developers.google.com/apis/library/sheets.googleapis.com?) on the Google Developer website. +- [Spreadsheet Gateway](https://github.com/SuperFlyTV/spreadsheet-gateway) GitHub Page for Developers diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/intro.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/intro.md new file mode 100644 index 0000000000..cf2c62a508 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/intro.md @@ -0,0 +1,14 @@ +# Rundown & Newsroom Systems + +Sofie Core doesn't talk directly to the newsroom systems, but instead via one of the Gateways. + +The Google Spreadsheet Gateway, iNEWS Gateway, and the MOS \( [Media Object Server Communications Protocol](http://mosprotocol.com/) \) Gateway which can handle interacting with any system that communicates via MOS. + +### Further Reading + +* [MOS Protocol Overview & Documentation](http://mosprotocol.com/) +* [iNEWS on Avid's Website](https://www.avid.com/products/inews/how-to-buy) +* [ENPS on The Associated Press' Website](https://www.ap.org/enps/support) + + + diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/mos-gateway.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/mos-gateway.md new file mode 100644 index 0000000000..8a2a60145c --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-a-gateway/rundown-or-newsroom-system-connection/mos-gateway.md @@ -0,0 +1,9 @@ +# MOS Gateway + +The MOS Gateway communicates with a device that supports the [MOS protocol](http://mosprotocol.com/wp-content/MOS-Protocol-Documents/MOS-Protocol-2.8.4-Current.htm) to ingest and remain in sync with a rundown. It can connect to any editorial system \(NRCS\) that uses version 2.8.4 of the MOS protocol, such as ENPS, and sync their rundowns with the _Sofie Core_. The rundowns are kept updated in real time and any changes made will be seen in the Sofie GUI. + +The setup for the MOS Gateway is handled in the Docker Compose in the [Quick Install](../../installing-sofie-server-core.md) page. + +One thing to note if managing the mos-gateway manually: It needs a few ports open \(10540, 10541\) for MOS-messages to be pushed to it from the NCS. + + diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-blueprints.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-blueprints.md new file mode 100644 index 0000000000..34796bbb1d --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-blueprints.md @@ -0,0 +1,46 @@ +--- +sidebar_position: 4 +--- + +# Installing Blueprints + +#### Prerequisites + +- [Installed and running Sofie Core](installing-sofie-server-core.md) +- [Initial Sofie Core Setup](initial-sofie-core-setup.md) + +Blueprints are little plug-in programs that runs inside _Sofie_. They are the logic that determines how _Sofie_ interacts with rundowns, hardware, and media. + +Blueprints are custom scripts that you create yourself \(or download an existing one\). There are a set of example Blueprints for the Spreadsheet Gateway available for use here: [https://github.com/SuperFlyTV/sofie-demo-blueprints](https://github.com/SuperFlyTV/sofie-demo-blueprints). + +To begin installing any Blueprint, navigate to the _Settings page_. Getting there is covered in the [Access Levels](../features/access-levels.md) page. + +![The Settings Page](/img/docs/getting-started/settings-page.jpg) + +To upload a new blueprint, click the _+_ icon next to Blueprints menu option. Select the newly created Blueprint and upload the local blueprint JS file. You will get a confirmation if the installation was successful. + +There are 3 types of blueprints: System, Studio and Show Style: + +### System Blueprint + +_System Blueprints handles some basic functionality on how the Sofie system will operate._ + +After you've uploaded the your system-blueprint js-file, click _Assign_ in the blueprint-page to assign it as system-blueprint. + +### Studio Blueprint + +_Studio Blueprints determine how Sofie will interact with the hardware in your studio._ + +After you've uploaded the your studio-blueprint js-file, navigate to a Studio in the settings and assign the new Blueprint to it \(under the label _Blueprint_ \). + +After having installed the Blueprint, the Studio's baseline will need to be reloaded. On the Studio page, click the button _Reload Baseline_. This will also be needed whenever you have changed any settings. + +### Show Style Blueprint + +_Show Style Blueprints determine how your show will look / feel._ + +After you've uploaded the your show-style-blueprint js-file, navigate to a Show Style in the settings and assign the new Blueprint to it \(under the label _Blueprint_ \). + +### Further Reading + +- [Blueprints Supporting the Spreadsheet Gateway](https://github.com/SuperFlyTV/sofie-demo-blueprints) diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/README.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/README.md new file mode 100644 index 0000000000..4d35fb277d --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/README.md @@ -0,0 +1,35 @@ +# Additional Software & Hardware + +#### Prerequisites + +* [Installed and running Sofie Core](../installing-sofie-server-core.md) +* [Installed Playout Gateway](../installing-a-gateway/playout-gateway.md) +* [Installed and configured Studio Blueprints](../installing-blueprints.md#installing-a-studio-blueprint) + +The following pages are broken up by equipment type that is supported by Sofie's Gateways. + +## Playout & Recording +* [CasparCG Graphics and Video Server](casparcg-server-installation.md) - _Graphics / Playout / Recording_ +* [Blackmagic Design's HyperDeck](https://www.blackmagicdesign.com/products/hyperdeckstudio) - _Recording_ +* [Quantel](http://www.quantel.com) Solutions - _Playout_ +* [Vizrt](https://www.vizrt.com/) Graphics Solutions - _Graphics / Playout_ + +## Vision Mixers +* [Blackmagic's ATEM](https://www.blackmagicdesign.com/products/atem) hardware vision mixers +* [vMix](https://www.vmix.com/) software vision mixer \(coming soon\) + +## Audio Mixers +* [Sisyfos](https://github.com/olzzon/sisyfos-audio-controller) audio controller +* [Lawo sound mixers_,_](https://www.lawo.com/applications/broadcast-production/audio-consoles.html) _using emberplus protocol_ +* Generic OSC \(open sound control\) + +## PTZ Cameras +* [Panasonic PTZ](https://pro-av.panasonic.net/en/products/ptz_camera_systems.html) cameras + +## Lights +* [Pharos](https://www.pharoscontrols.com/) light control + +## Other +* Generic OSC \(open sound control\) +* Generic HTTP requests \(to control http-REST interfaces\) +* Generic TCP-socket diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/_category_.json b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/_category_.json new file mode 100644 index 0000000000..d3e1e8979e --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Installing Connections and Additional Hardware", + "position": 6 +} \ No newline at end of file diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/casparcg-server-installation.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/casparcg-server-installation.md new file mode 100644 index 0000000000..7ee0d5496d --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/casparcg-server-installation.md @@ -0,0 +1,233 @@ +--- +title: Installing CasparCG Server for Sofie +description: Sofie specific fork of CasparCG Server 2.1 +--- + +# Installing CasparCG Server for Sofie + +Although CasparCG Server is an open source program that is free to use for both personal and cooperate applications, the hardware needed to create and execute high quality graphics is not. You can get a preview running without any additional hardware but, it is not recommended to use CasparCG Server for production in this manner. To begin, you will install the CasparCG Server on your machine then add the additional configuration needed for your setup of choice. + +## Installing the CasparCG Server + +To begin, download the latest release of [CasparCG Server from GitHub](https://github.com/nrkno/sofie-casparcg-server/releases). There are multiple versions of CasparCG Server available to the public for download but, you specifically want the latest NRK version. + +Once downloaded, extract the files and navigate down the folders, _CasparCG Server_ then _Server_. This folder contains your CasparCG Server Configuration file, `casparcg.config`, and your CasparCG Server executable, `casparcg.exe`. + +How you will configure the CasparCG Server will depend on the number of DeckLink cards your machine contains. The first subsection for each CasparCG Server setup, labeled _Channels_, will contain the unique portion of the configuration. The following is the majority of the configuration file that will be consistent between setups. + +```markup + + + debug + + false + + + + + media/ + log/ + data/ + template/ + thumbnail/ + font/ + + secret + + + + + + 5250 + AMCP + + + 3250 + LOG + + + +``` + +One additional note, the Server does require the configuration file be named `casparcg.config`. + +### Installing CasparCG Media Scanner + +You can use the CasparCG Media Scanner to locate and add all of your media to the _Sofie Core_. To install the Media Scanner, you will go to the [project's Release page](https://github.com/nrkno/sofie-media-scanner/releases) and download the `.zip` file under the latest release. Similar to the CasparCG Server, you want to use the NRK version. + +Once downloaded and extracted, move the `scanner.exe` file to the same folder as your `casparcg.exe` file. + +### Installing the CasparCG Launcher + +You can launch both of your CasparCG applications with the[ CasparCG Launcher.](https://github.com/nrkno/sofie-casparcg-launcher) Download the `.exe` file in the latest release and once complete, move the file to the same folder as your `casparcg.exe` file. + +## Configuring Windows + +### Required Software + +Windows will require you install [Microsoft's Visual C++ 2015 Redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=52685) to run the CasparCG Server properly. Before downloading the redistributable, please ensure it is not already installed on your system. Open your programs list and in the popup window, you can search for _C++_ in the search field. If _Visual C++ 2015_ appears, you do not need install the redistributable. + +If you need to install redistributable then, navigate to [Microsoft's website](https://www.microsoft.com/en-us/download/details.aspx?id=52685) and download it from there. Once downloaded, you can run the `.exe` file and follow the prompts. + +## Hardware Recommendations + +Although CasparCG Server can be run on some lower end hardware, it is only recommended to do so for non-production uses. Below is a table of the minimum and preferred specs depending on what type of system you are using. + +| System Type | Min CPU | Pref CPU | Min GPU | Pref GPU | Min Storage | Pref Storage | +| :------------ | :--------------- | :------------------------ | :------- | :----------- | :------------- | :------------- | +| Development | i5 Gen 6i7 Gen 6 | GTX 1050 | GTX 1060 | GTX 1060 | NVMe SSD 500gb | | +| Prod, 1 Card | i7 Gen 6 | i7 Gen 7 | GTX 1060 | GTX 1070 | NVMe SSD 500gb | NVMe SSD 500gb | +| Prod, 2 Cards | i9 Gen 8 | i9 Gen 10 Extreme Edition | RTX 2070 | Quadro P4000 | Dual Drives | Dual Drives | + +For _dual drives_, it is recommended to use a smaller 250gb NVMe SSD for the operating system. Then a faster 1tb NVMe SSD for the CasparCG Server and media. It is also recommended to buy a drive with about 40% storage overhead. This is for SSD p~~e~~rformance reasons and Sofie will warn you about this if your drive usage exceeds 60%. + +### DeckLink Cards + +There are a few SDI cards made by Blackmagic Design that are supported by CasparCG. The base model, with four bi-directional input and outputs, is the [Duo 2](https://www.blackmagicdesign.com/products/decklink/techspecs/W-DLK-31). If you need additional channels, use the[ Quad 4](https://www.blackmagicdesign.com/products/decklink/techspecs/W-DLK-30) which supports eight bi-directional inputs and outputs. Be aware the BNC connections are not the standard BNC type. B&H offers [Mini BNC to BNC connecters](https://www.bhphotovideo.com/c/product/1462647-REG/canare_cal33mb018_mini_rg59_12g_sdi_4k.html). Finally, for 4k support, use the [8K Pro](https://www.blackmagicdesign.com/products/decklink/techspecs/W-DLK-34) which has four bi-directional BNC connections and one reference connection. + +Here is the Blackmagic Design PDF for [installing your DeckLink card \( Desktop Video Device \).](https://documents.blackmagicdesign.com/UserManuals/DesktopVideoManual.pdf) + +Once the card in installed in your machine, you will need to download the controller from Blackmagic's website. Navigate to [this support page](https://www.blackmagicdesign.com/support/family/capture-and-playback), it will only display Desktop Video Support, and in the _Latest Downloads_ column download the most recent version of _Desktop Video_. Before installing, save your work because Blackmagic's installers will force you to restart your machine. + +Once booted back up, you should be able to launch the Desktop Video application and see your DeckLink card. + +![Blackmagic Design's Desktop Video Application](/img/docs/installation/installing-connections-and-additional-hardware/desktop-video.png) + +Click the icon in the center of the screen to open the setup window. Each production situation will very in frame rate and resolution so go through the settings and set what you know. Most things are set to standards based on your region so the default option will most likely be correct. + +![Desktop Video Settings](/img/docs/installation/installing-connections-and-additional-hardware/desktop-video-settings.png) + +If you chose a DeckLink Duo, then you will also need to set SDI connectors one and two to be your outputs. + +![DeckLink Duo SDI Output Settings](/img/docs/installation/installing-connections-and-additional-hardware/decklink_duo_card.png) + +## Hardware-specific Configurations + +### Preview Only \(Basic\) + +A preview only version of CasparCG Server does not lack any of the features of a production version. It is called a _preview only_ version because the standard outputs on a computer, without a DeckLink card, do not meet the requirements of a high quality broadcast graphics machine. It is perfectly suitable for development though. + +#### Required Hardware + +No additional hardware is required, just the computer you have been using to follow this guide. + +#### Configuration + +The default configuration will give you one preview window. No additional changes need to be made. + +### Single DeckLink Card \(Production Minimum\) + +#### Required Hardware + +To be production ready, you will need to output an SDI or HDMI signal from your production machine. CasparCG Server supports Blackmagic Design's DeckLink cards because they provide a key generator which will aid in keeping the alpha and fill channels of your graphics in sync. Please review the [DeckLink Cards](casparcg-server-installation.md#decklink-cards) section of this page to choose which card will best fit your production needs. + +#### Configuration + +You will need to add an additional consumer to your`caspar.config` file to output from your DeckLink card. After the screen consumer, add your new DeckLink consumer like so. + +```markup + + + 1080i5000 + stereo + + + 1 + true + + + + + 1 + 1 + true + stereo + normal + external_separate_device + false + 3 + + + + + +``` + +You may no longer need the screen consumer. If so, you can remove it and all of it's contents. This will dramatically improve overall performance. + +### Multiple DeckLink Cards \(Recommended Production Setup\) + +#### Required Hardware + +For a preferred production setup you want a minimum of two DeckLink Duo 2 cards. This is so you can use one card to preview your media, while your second card will support the program video and audio feeds. For CasparCG Server to recognize both cards, you need to add two additional channels to the `caspar.config` file. + +```markup + + + 1080i5000 + stereo + + + 1 + true + + + + + 1 + 1 + true + stereo + normal + external_separate_device + false + 3 + + + + + 2 + 2 + true + stereo + normal + external_separate_device + false + 3 + + + + + +``` + +### Validating the Configuration File + +Once you have setup the configuration file, you can use an online validator to check and make sure it is setup correctly. Navigate to the [CasparCG Server Config Validator](https://casparcg.net/validator/) and paste in your entire configuration file. If there are any errors, they will be displayed at the bottom of the page. + +### Launching the Server + +Launching the Server is the same for each hardware setup. This means you can run`casparcg-launcher.exe` and the server and media scanner will start. There will be two additional warning from Windows. The first is about the EXE file and can be bypassed by selecting _Advanced_ and then _Run Anyways_. The second menu will be about CasparCG Server attempting to access your firewall. You will need to allow access. + +A window will open and display the status for the server and scanner. You can start, stop, and/or restart the server from here if needed. An additional window should have opened as well. This is the main output of your CasparCG Server and will contain nothing but a black background for now. If you have a DeckLink card installed, its output will also be black. + +## Connecting Sofie to the CasparCG Server + +Now that your CasparCG Server software is running, you can connect it to the _Sofie Core_. Navigate back to the _Settings page_ and in the menu, select the _Playout Gateway_. If the _Playout Gateway's_ status does not read _Good_, then please review the [Installing and Setting up the Playout Gateway](../installing-a-gateway/playout-gateway.md) section of this guide. + +Under the Sub Devices section, you can add a new device with the _+_ button. Then select the pencil \( edit \) icon on the new device to open the sub device's settings. Select the _Device Type_ option and choose _CasparCG_ from the drop down menu. Some additional fields will be added to the form. + +The _Host_ and _Launcher Host_ fields will be _localhost_. The _Port_ will be CasparCG's TCP port responsible for handling the AMCP commands. It defaults to 5052 in the `casparcg.config` file. The _Launcher Port_ will be the CasparCG Launcher's port for handling HTTP requests. It will default to 8005 and can be changed in the _Launcher's settings page_. Once all four fields are filled out, you can click the check mark to save the device. + +In the _Attached Sub Devices_ section, you should now see the status of the CasparCG Server. You may need to restart the Playout Gateway if the status is _Bad_. + +## Further Reading + +- [CasparCG Server Releases](https://github.com/nrkno/sofie-casparcg-server/releases) on GitHub. +- [Media Scanner Releases](https://github.com/nrkno/sofie-media-scanner/releases) on GitHub. +- [CasparCG Launcher](https://github.com/nrkno/sofie-casparcg-launcher) on GitHub. +- [Microsoft Visual C++ 2015 Redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=52685) on Microsoft's website. +- [Blackmagic Design's DeckLink Cards](https://www.blackmagicdesign.com/products/decklink/models) on Blackmagic's website. Check the [DeckLink cards](casparcg-server-installation.md#decklink-cards) section for compatibility. +- [Installing a DeckLink Card](https://documents.blackmagicdesign.com/UserManuals/DesktopVideoManual.pdf) as a PDF. +- [Desktop Video Download Page](https://www.blackmagicdesign.com/support/family/capture-and-playback) on Blackmagic's website. +- [CasparCG Configuration Validator](https://casparcg.net/validator/) diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/ffmpeg-installation.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/ffmpeg-installation.md new file mode 100644 index 0000000000..6d80150698 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/ffmpeg-installation.md @@ -0,0 +1,35 @@ +# Adding FFmpeg and FFprobe to your PATH on Windows + +Some parts of Sofie (specifically the Package Manager) require that [`FFmpeg`](https://www.ffmpeg.org/) and [`FFprobe`](https://ffmpeg.org/ffprobe.html) be available in your `PATH` environment variable. This guide will go over how to download these executables and add them to your `PATH`. + +### Installation + +1. `FFmpeg` and `FFprobe` can be downloaded from the [FFmpeg Downloads page](https://ffmpeg.org/download.html) under the "Get packages & executable files" heading. At the time of writing, there are two sources of Windows builds: `gyan.dev` and `BtbN` -- either one will work. +2. Once downloaded, extract the archive to some place permanent such as `C:\Program Files\FFmpeg`. + - You should end up with a `bin` folder inside of `C:\Program Files\FFmpeg` and in that `bin` folder should be three executables: `ffmpeg.exe`, `ffprobe.exe`, and `ffplay.exe`. +3. Open your Start Menu and type `path`. An option named "Edit the system environment variables" should come up. Click on that option to open the System Properties menu. + + ![Start Menu screenshot](/img/docs/edit_system_environment_variables.jpg) + +4. In the System Properties menu, click the "Environment Varibles..." button at the bottom of the "Advanced" tab. + + ![System Properties screenshot](/img/docs/system_properties.png) + +5. If you installed `FFmpeg` and `FFprobe` to a system-wide location such as `C:\Program Files\FFmpeg`, select and edit the `Path` variable under the "System variables" heading. Else, if you installed them to some place specific to your user account, edit the `Path` variable under the "User variables for " heading. + + ![Environment Variables screenshot](/img/docs/environment_variables.png) + +6. In the window that pops up when you click "Edit...", click "New" and enter the path to the `bin` folder you extracted earlier. Then, click OK to add it. + + ![Edit environment variable screenshot](/img/docs/edit_path_environment_variable.png) + +7. Click "OK" to close the Environment Variables window, and then click "OK" again to close the + System Properties window. +8. Verify that it worked by opening a Command Prompt and executing the following commands: + + ```cmd + ffmpeg -version + ffprobe -version + ``` + + If you see version output from both of those commands, then you are all set! If not, double check the paths you entered and try restarting your computer. diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/vision-mixers.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/vision-mixers.md new file mode 100644 index 0000000000..1515b08840 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/vision-mixers.md @@ -0,0 +1,14 @@ +# Configuring Vision Mixers + +## ATEM – Blackmagic Design + +The [Playout Gateway](../installing-a-gateway/playout-gateway.md) supports communicating with the entire line up of Blackmagic Design's ATEM vision mixers. + +### Connecting Sofie + +Once your ATEM is properly configured on the network, you can add it as a device to the Sofie Core. To begin, navigate to the _Settings page_ and select the _Playout Gateway_ under _Devices_. Under the _Sub Devices_ section, you can add a new device with the _+_ button. Edit it the new device with the pencil \( edit \) icon add the host IP and port for your ATEM. Once complete, you should see your ATEM in the _Attached Sub Devices_ section with a _Good_ status indicator. + +### Additional Information + +Sofie does not support connecting to a vision mixer hardware panels. All interacts with the vision mixers must be handled within a Rundown. + diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-input-gateway.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-input-gateway.md new file mode 100644 index 0000000000..5d809d74af --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-input-gateway.md @@ -0,0 +1,34 @@ +# Input Gateway + +The Input Gateway handles control devices that are not capable of running a Web Browser. This allows Sofie to integrate directly with devices such as: Hardware Panels, GPI input, MIDI devices and external systems being able to send an HTTP Request. + +To install it, begin by downloading the latest release of [Input Gateway from GitHub](https://github.com/nrkno/sofie-input-gateway/releases). You can now run the `input-gateway.exe` file inside the extracted folder. A warning window may popup about the app being unrecognized. You can get around this by selecting _More Info_ and clicking _Run Anyways_. + +Much like [Package Manager](./installing-package-manager), the Sofie instance that Input Gateway needs to connect to is configured through command line arguments. A minimal configuration could look something like this. + +```bash +input-gateway.exe --host --port --https --id --token +``` + +If not connecting over HTTPS, remove the `--https` flag. + +Input Gateway can be launched from [CasparCG Launcher](./installing-connections-and-additional-hardware/casparcg-server-installation#installing-the-casparcg-launcher). This will make management and log collection easier on a production system. + +You can now open the _Sofie Core_, `http://localhost:3000`, and navigate to the _Settings page_. You will see your _Input Gateway_ under the _Devices_ section of the menu. In _Input Devices_ you can add devices that this instance of Input Gateway should handle. Some of the device integrations will allow you to customize the Feedback behavior. The *Device ID* property will identify a given Input Device in the Studio, so this property can be used for fail-over purposes. + +## Supported devices and protocols + +Currently, input gateway supports: + +* Stream Deck panels +* Skaarhoj panels - _TCP Raw Panel_ mode +* X-Keys panels +* MIDI controllers +* OSC +* HTTP + +### Further Reading + +* [Input Gateway Releases on GitHub](https://github.com/nrkno/sofie-input-gateway/releases) +* [Input Gateway GitHub Page for Developers](https://github.com/nrkno/sofie-input-gateway) + diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-package-manager.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-package-manager.md new file mode 100644 index 0000000000..bd6cbf3a15 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-package-manager.md @@ -0,0 +1,93 @@ +--- +sidebar_position: 7 +--- + +# Installing Package Manager + +### Prerequisites + +- [Installed and running Sofie Core](installing-sofie-server-core.md) +- [Initial Sofie Core Setup](initial-sofie-core-setup.md) +- [Installed and configured Demo Blueprints](https://github.com/SuperFlyTV/sofie-demo-blueprints) +- [Installed, configured, and running CasparCG Server](installing-connections-and-additional-hardware/casparcg-server-installation.md) +- [`FFmpeg` and `FFprobe` available in `PATH`](installing-connections-and-additional-hardware/ffmpeg-installation.md) + +Package Manager is used by Sofie to copy, analyze, and process media files. It is what powers Sofie's ability to copy media files to playout devices, to know when a media file is ready for playout, and to display details about media files in the rundown view such as scene changes, black frames, freeze frames, and more. + +Although Package Manager can be used to copy any kind of file to/from a wide array of devices, we'll be focusing on a basic CasparCG Server Server setup for this guide. + +:::caution + +At this time, the Package Manager worker process is Windows-only. Therefore, these instructions as a whole will only work on Windows. The worker will not work on WSL2. + +::: + +## Installation For Development (Quick Start) + +Package Manager is a suite of standalone applications, separate from _Sofie Core_. This guide assumes that Package Manager will be running on the same computer as _CasparCG Server_ and _Sofie Core_, as that is the fastest way to set up a demo. To get all parts of _Package Manager_ up and running quickly, execute these commands: + +```bash +git clone https://github.com/nrkno/sofie-package-manager.git +cd sofie-package-manager +yarn install +yarn build +yarn start:single-app -- -- --basePath "C:\your\path\to\casparcg-server\media-folder (i.e. sofie-demo-media)" +``` + +Note: if Powershell throws `Unknown argument: basePath` error, add one more pair of dashes (`--`) before the basePath argument: + +```bash +yarn start:single-app -- -- -- --basePath "C:\your\path\to\casparcg-server\media-folder (i.e. sofie-demo-media)" +``` + +On first startup, Package Manager will exit with the following message: + +``` +Not setup yet, exiting process! +To setup, go into Core and add this device to a Studio +``` + +This first run is necessary to get the Package Manager device registered with _Sofie Core_. We'll restart Package Manager later on in the [Configuration](#configuration) instructions. + + +## Installation In Production + +We provide pre-built executables for Windows (x64) systems that can be used in production environments. These can be found on the [Releases](https://github.com/nrkno/sofie-package-manager/releases) GitHub repository page for Package Manager. For a minimal installation, you'll need the `package-manager-single-app.exe` and `worker.exe`. Put them in a folder of your choice. You can also place `ffmpeg.exe` and `ffprobe.exe` alongside them, if you don't want to make them available in `PATH`. + +```bash +package-manager-single-app.exe --coreHost= --corePort= --deviceId= --deviceToken= +``` + +Package Manager can be launched from [CasparCG Launcher](./installing-connections-and-additional-hardware/casparcg-server-installation.md#installing-the-casparcg-launcher) alongside Caspar-CG. This will make management and log collection easier on a production Video Server. + +You can see a list of available options by running `package-manager-single-app.exe --help`. + +## Configuration + +1. Open the _Sofie Core_ Settings page ([http://localhost:3000/settings?admin=1](http://localhost:3000/settings?admin=1)), click on your Studio, and scroll down to the Attached Devices section. +1. Click the plus button (`+`) and select Package Manager to add the Package Manager device to your Studio. +1. On this same settings page, scroll down to the Package Manager section. +1. Click the plus button under the Package Containers heading, then click the edit icon (pencil) to the right of the newly-created package container. +1. Give this package container an ID of `casparcgContainer0` and a label of `CasparCG Package Container`. +1. Click on the dropdown under "Playout devices which use this package container" and select `casparcg0`. + - If you don't have a `casparcg0` device, add it to the Playout Gateway under the Devices heading, then restart the Playout Gateway. +1. Click the plus button under "Accessors", then click the edit icon to the right of the newly-created accessor. +1. Give this accessor an ID of `casparcgHttpProxy0`, a Label of `CasparCG HTTP Proxy Accessor`, an Accessor Type of `HTTP_PROXY`, and a Base URL of `http://localhost:8080/package`. Then, ensure that both the "Allow Read access" and "Allow Write access" boxes are checked. Finally, click the done button (checkmark icon) in the bottom right. +1. Scroll back up a bit to the "Studio Settings" subsection (still in the Package Manager section) and select "CasparCG Package Container" for both "Package Containers to use for previews" and "Package Containers to use for thumbnails". +1. Your settings should look like this once all the above steps have been completed: + ![Package Manager demo settings](/img/docs/Package_Manager_demo_settings.png) +1. If Package Manager `start:single-app` is running, restart it. If not, start it (see the above [Installation instructions](#installation-quick-start) for the relevant command line). + +## Usage + +In this basic configuration, Package Manager won't be copying any packages into your CasparCG Server media folder. Instead, it will simply check that the files in the rundown are present in your CasparCG Server media folder, and you'll have to manually place those files in the correct directory. However, thumbnail and preview generation will still function, as will status reporting. + +If you're using the demo rundown provided by the [Rundown Editor](rundown-editor.md), you should already see work statuses on the Package Status page ([Status > Packages](http://localhost:3000/status/expected-packages)). + +![Example Package Manager status display](/img/docs/Package_Manager_status_example.jpg) + +If all is good, head to the [Rundowns page](http://localhost:3000/rundowns) and open the demo rundown. + +### Further Reading + +- [Package Manager](https://github.com/nrkno/sofie-package-manager) on GitHub. diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-sofie-server-core.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-sofie-server-core.md new file mode 100644 index 0000000000..2a07e4c960 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-sofie-server-core.md @@ -0,0 +1,139 @@ +--- +sidebar_position: 2 +--- + +# Quick install + +## Installing for testing \(or production\) + +### **Prerequisites** + +**\(Linux\)** Install [Docker](https://docs.docker.com/install/linux/docker-ce/ubuntu/) and [docker-compose](https://www.digitalocean.com/community/tutorials/how-to-install-docker-compose-on-ubuntu-18-04). +**\(Windows\)** Install [Docker for Windows](https://hub.docker.com/editions/community/docker-ce-desktop-windows). + +### Installation + +This docker-compose file automates the basic setup of the [Sofie-Core application](../../for-developers/libraries.md#main-application), the backend database and different Gateway options. + +```yaml +# This is NOT recommended to be used for a production deployment. +# It aims to quickly get an evaluation version of Sofie running and serve as a basis for how to set up a production deployment. +version: '3.3' +services: + db: + hostname: mongo + image: mongo:4.2.18 + restart: always + entrypoint: ['/usr/bin/mongod', '--replSet', 'rs0', '--bind_ip_all'] + # the healthcheck avoids the need to initiate the replica set + healthcheck: + test: test $$(echo "rs.initiate().ok || rs.status().ok" | mongo --quiet) -eq 1 + interval: 10s + start_period: 30s + ports: + - '27017:27017' + volumes: + - db-data:/data/db + networks: + - sofie + + core: + hostname: core + image: sofietv/tv-automation-server-core:release37 + restart: always + ports: + - '3000:3000' # Same port as meteor uses by default + environment: + PORT: '3000' + MONGO_URL: 'mongodb://db:27017/meteor' + MONGO_OPLOG_URL: 'mongodb://db:27017/local' + ROOT_URL: 'http://localhost:3000' + SOFIE_STORE_PATH: '/mnt/sofie-store' + networks: + - sofie + volumes: + - sofie-store:/mnt/sofie-store + depends_on: + - db + + playout-gateway: + image: sofietv/tv-automation-playout-gateway:release37 + restart: always + command: yarn start -host core -port 3000 -id playoutGateway0 + networks: + - sofie + - lan_access + depends_on: + - core + + # Choose one of the following images, depending on which type of ingest gateway is wanted. + # If using the Rundown Editor, then none of the below images are needed. + # The Rundown Editor can be found here: https://github.com/SuperFlyTV/sofie-automation-rundown-editor + + # spreadsheet-gateway: + # image: superflytv/sofie-spreadsheet-gateway:latest + # restart: always + # command: yarn start -host core -port 3000 -id spreadsheetGateway0 + # networks: + # - sofie + # depends_on: + # - core + + # mos-gateway: + # image: sofietv/tv-automation-mos-gateway:release37 + # restart: always + # ports: + # - "10540:10540" # MOS Lower port + # - "10541:10541" # MOS Upper port + # # - "10542:10542" # MOS query port - not used + # command: yarn start -host core -port 3000 -id mosGateway0 + # networks: + # - sofie + # depends_on: + # - core + + # inews-gateway: + # image: tv2media/inews-ftp-gateway:1.37.0-in-testing.20 + # restart: always + # command: yarn start -host core -port 3000 -id inewsGateway0 + # networks: + # - sofie + # depends_on: + # - core + +networks: + sofie: + lan_access: + driver: bridge + +volumes: + db-data: + sofie-store: +``` + +Create a `Sofie` folder, copy the above content, and save it as `docker-compose.yaml` within the `Sofie` folder. + +Navigate to the _ingest-gateway_ section of `docker-compose.yaml` and select which type of _ingest-gateway_ you'd like installed by uncommenting it. Save your changes. If you are using the [Rundown Editor](rundown-editor.md), then no ingest gateways need to be uncommented. + +Then open a terminal, `cd your-sofie-folder` and `sudo docker-compose up` \(just `docker-compose up` on Windows\). + +Once the installation is done, Sofie should be running on [http://localhost:3000](http://localhost:3000) + +Next, you will need to install a Rundown Gateway. Visit [Rundowns & Newsroom Systems](installing-a-gateway/rundown-or-newsroom-system-connection/intro.md) to see which _Rundown Gateway_ is best suited for _your_ production environment. + +### Tips for running in production + +There are some things not covered in this guide needed to run _Sofie_ in a production environment: + +- Logging: Collect, store and track error messages. [Kibana](https://www.elastic.co/kibana) and [logstash](https://www.elastic.co/logstash) is one way to do it. +- NGINX: It is customary to put a load-balancer in front of _Sofie Core_. +- Memory and CPU usage monitoring. + +## Installing for Development + +Installation instructions for installing Sofie-Core or the various gateways are available in the README file in their respective github repos. + +Common prerequisites are [Node.js](https://nodejs.org/) and [Yarn](https://yarnpkg.com/). +Links to the repos are listed at [Applications & Libraries](../../for-developers/libraries.md). + +[_Sofie Core_ GitHub Page for Developers](https://github.com/nrkno/sofie-core) diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/intro.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/intro.md new file mode 100644 index 0000000000..c3a14c218b --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/intro.md @@ -0,0 +1,37 @@ +--- +sidebar_position: 1 +--- +# Getting Started + +_Sofie_ can be installed in many different ways, depending on which platforms, needs, and features you desire. The _Sofie_ system consists of several applications that work together to provide complete broadcast automation system. Each of these components' installation will be covered in this guide. Additional information about the products or services mentioned alongside the Sofie Installation can be found on the [Further Reading](../further-reading.md). + +There are four minimum required components to get a Sofie system up and running. First you need the [_Sofie Core_](installing-sofie-server-core.md), which is the brains of the operation. Then a set of [_Blueprints_](installing-blueprints.md) to handle and interpret incoming and outgoing data. Next, an [_Ingest Gateway_](installing-a-gateway/rundown-or-newsroom-system-connection/intro.md) to fetch the data for the Blueprints. Then finally, a [_Playout Gateway_](installing-a-gateway/playout-gateway.md) to send the data to your playout device of choice. + + + +## Sofie Core View + +The _Rundowns_ view will display all the active rundowns that the _Sofie Core_ has access to. + +![Rundown View](/img/docs/getting-started/rundowns-in-sofie.png) + +The _Status_ views displays the current status for the attached devices and gateways. + +![Status View – Describes the state of _Sofie Core_](/img/docs/getting-started/status-page.jpg) + +The _Settings_ views contains various settings for the studio, show styles, blueprints etc.. If the link to the settings view is not visible in your application, check your [Access Levels](../features/access-levels.md). More info on specific parts of the _Settings_ view can be found in their corresponding guide sections. + +![Settings View – Describes how the _Sofie Core_ is configured](/img/docs/getting-started/settings-page.jpg) + +## Sofie Core Overview + +The _Sofie Core_ is the primary application for managing the broadcast but, it doesn't play anything out on it's own. You need to use Gateways to establish the connection from the _Sofie Core_ to other pieces of hardware or remote software. + +### Gateways + +Gateways are separate applications that bridge the gap between the _Sofie Core_ and other pieces of hardware or services. At minimum, you will need a _Playout Gateway_ so your timeline can interact with your playout system of choice. To install the _Playout Gateway_, visit the [Installing a Gateway](installing-a-gateway/intro.md) section of this guide and for a more in-depth look, please see [Gateways](../concepts-and-architecture.md#gateways). + +### Blueprints + +Blueprints can be described as the logic that determines how a studio and show should interact with one another. They interpret the data coming in from the rundowns and transform them into a rich set of playable elements \(_Segments_, _Parts_, _AdLibs,_ etcetera\). The _Sofie Core_ has three main blueprint types, _System Blueprints_, _Studio Blueprints_, and _Showstyle Blueprints_. Installing _Sofie_ does not require you understand what these blueprints do, just that they are required for the _Sofie Core_ to work. If you would like to gain a deeper understand of how _Blueprints_ work, please visit the [Blueprints](#blueprints) section. + diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/media-manager.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/media-manager.md new file mode 100644 index 0000000000..c286df52c3 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/media-manager.md @@ -0,0 +1,21 @@ +--- +sidebar_position: 100 +--- + +# Media Manager + +:::caution + +Media Manager is deprecated and is not recommended for new deployments. There are known issues that won't be fixed and the API's it is using to interface with Sofie will be removed. + +::: + +The Media Manager handles the media, or files, that make up the rundown content. To install it, begin by downloading the latest release of [Media Manager from GitHub](https://github.com/nrkno/sofie-media-management/releases). You can now run the `media-manager.exe` file inside the extracted folder. A warning window may popup about the app being unrecognized. You can get around this by selecting _More Info_ and clicking _Run Anyways_. A terminal window will open and begin running the application. + +You can now open the _Sofie Core_, `http://localhost:3000`, and navigate to the _Settings page_. You will see your _Media Manager_ under the _Devices_ section of the menu. The four main sections, general properties, attached storage, media flows, monitors, as well as attached subdivides, all contribute to how the media is handled within the Sofie Core. + +### Further Reading + +* [Media Manager Releases on GitHub](https://github.com/nrkno/sofie-media-management/releases) +* [Media Manager GitHub Page for Developers](https://github.com/nrkno/sofie-media-management) + diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/rundown-editor.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/rundown-editor.md new file mode 100644 index 0000000000..b46e173d08 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/rundown-editor.md @@ -0,0 +1,11 @@ +--- +sidebar_position: 8 +--- + +# Sofie Rundown Editor + +Sofie Rundown Editor is a tool for creating and editing rundowns in a _demo_ environment of Sofie, without the use of an iNews, Spreadsheet or MOS Gateway + +### Installing Sofie Rundown Editor + +Check the installation instructions on the [project repository](https://github.com/SuperFlyTV/sofie-automation-rundown-editor). diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/intro.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/intro.md new file mode 100644 index 0000000000..4bf6b039a9 --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/intro.md @@ -0,0 +1,41 @@ +--- +sidebar_label: Introduction +sidebar_position: 0 +--- + +# Sofie User Guide + +## Key Features + +### Web-based GUI + +![Producer's / Director's View](/img/docs/Sofie_GUI_example.jpg) + +![Warnings and notifications are displayed to the user in the GUI](/img/docs/warnings-and-notifications.png) + +![The Host view, displaying time information and countdowns](/img/docs/host-view.png) + +![The prompter view](/img/docs/prompter-view.png) + +:::info +Tip: The different web views \(such as the host view and the prompter\) can easily be transmitted over an SDI signal using the HTML producer in [CasparCG](installation/installing-connections-and-additional-hardware/casparcg-server-installation.md). +::: + +### Modular Device Control + +Sofie controls playout devices \(such as vision and audio mixers, graphics and video playback\) via the Playout Gateway, using the [Timeline](concepts-and-architecture.md#timeline). +The Playout Gateway controls the devices and keeps track of their state and statuses, and lets the user know via the GUI if something's wrong that can affect the show. + +### _State-based Playout_ + +Sofie is using a state-based architecture to control playout. This means that each element in the show can be programmed independently - there's no need to take into account what has happened previously in the show; Sofie will make sure that the video is loaded and that the audio fader is tuned to the correct position, no matter what was played out previously. +This allows the producer to skip ahead or move backwards in a show, without the fear of things going wrong on air. + +### Modular Data Ingest + +Sofie features a modular ingest data-flow, allowing multiple types of input data to base rundowns on. Currently there is support for [MOS-based](http://mosprotocol.com) systems such as ENPS and iNEWS, as well as [Google Spreadsheets](installation/installing-a-gateway/rundown-or-newsroom-system-connection/installing-sofie-with-google-spreadsheet-support), and more is in development. + +### Blueprints + +The [Blueprints](concepts-and-architecture.md#blueprints) are plugins to _Sofie_, which allows for customization and tailor-made show designs. +The blueprints are made different depending on how the input data \(rundowns\) look like, how the show-design look like, and what devices to control. diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/supported-devices.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/supported-devices.md new file mode 100644 index 0000000000..55f27cd5ab --- /dev/null +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/supported-devices.md @@ -0,0 +1,118 @@ +--- +sidebar_position: 1.5 +--- +# Supported Playout Devices + +All playout devices are essentially driven through the _timeline_, which passes through _Sofie Core_ into the Playout Gateway where it is processed by the timeline-state-resolver. This page details which devices and what parts of the devices can be controlled through the timeline-state-resolver library. In general a blueprints developer can use the [timeline-state-resolver-types package](https://www.npmjs.com/package/timeline-state-resolver-types) to see the interfaces for the timeline objects used to control the devices. + +## Blackmagic Design's ATEM Vision Mixers + +We support almost all features of these devices except fairlight audio, camera controls and streaming capabilities. A non-inclusive list: + +* Control of camera inputs +* Transitions +* Full control of keyers +* Full control of DVE's +* Control of media pools +* Control of auxilliaries + +## CasparCG Server + +Tested and developed against [a fork of version 2.1](https://github.com/nrkno/sofie-casparcg-server) with more support for version 2.3 being added in the future. + +* Video playback +* Graphics playback +* Recording / streaming +* Mixer parameters +* Transitions + +## HTTP Protocol + +* GET/POST/PUT/DELETE methods +* Interval based watcher for status monitoring + +## Blackmagic Design HyperDeck + +* Recording + +## Lawo Powercore & MC2 Series + +* Control over faders + * Using the ramp function on the powercore +* Control of parameters in the ember tree + +## OSC protocol + +* Sending of integers, floats, strings, blobs +* Tweening \(transitioning between\) values + +Can be configured in TCP or UDP mode. + +## Panasonic PTZ Cameras + +* Recalling presets +* Setting zoom, zoom speed and recall speed + +## Pharos Lighting Control + +* Recalling scenes +* Recalling timelines + +## Grass Valley SQ Media Servers + +* Control of playback +* Looping +* Cloning + +_Note: some features are controlled through the Package Manager_ + +## Shotoku Camera Robotics + +* Cutting to shots +* Fading to shots + +## Singular Live + +* Control nodes + +_Note: this is not currently used in production by anyone we know of_ + +## Sisyfos + +* On-air controls +* Fader levels +* Labels +* Hide / show channels + +## TCP Protocol + +* Sending messages + +## VizRT Viz MSE + +* Pilot elements +* Continue commands +* Loading all elements +* Clearing all elements + +## vMix + +* Full M/E control +* Audio control +* Streaming / recording control +* Fade to black +* Overlays +* Transforms +* Transitions + +## OBS + +*Through OBS WebSocket v4 RPC API* + +* Current / Preview Scene +* Current Transition +* Recording +* Streaming +* Scene Item visibility +* Source Settings (FFmpeg source) +* Source Mute diff --git a/packages/documentation/versions.json b/packages/documentation/versions.json index f9c6d229be..c75ea5eab1 100644 --- a/packages/documentation/versions.json +++ b/packages/documentation/versions.json @@ -1,8 +1,9 @@ [ - "1.49.0", - "1.47.0", - "1.46.0", - "1.41.0", - "1.38.0", - "1.37.0" -] + "1.50.0", + "1.49.0", + "1.47.0", + "1.46.0", + "1.41.0", + "1.38.0", + "1.37.0" +] \ No newline at end of file From c99c2a6403c7959e26aa702d482b3f911c6dbbf0 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 29 Nov 2024 17:41:51 +0100 Subject: [PATCH 28/30] chore: fix 1.50.0 of documentation snapshot --- .../ffmpeg-installation.md | 2 +- .../version-1.50.0-sidebars.json | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 packages/documentation/versioned_sidebars/version-1.50.0-sidebars.json diff --git a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/ffmpeg-installation.md b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/ffmpeg-installation.md index 6d80150698..0843c76312 100644 --- a/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/ffmpeg-installation.md +++ b/packages/documentation/versioned_docs/version-1.50.0/user-guide/installation/installing-connections-and-additional-hardware/ffmpeg-installation.md @@ -15,7 +15,7 @@ Some parts of Sofie (specifically the Package Manager) require that [`FFmpeg`](h ![System Properties screenshot](/img/docs/system_properties.png) -5. If you installed `FFmpeg` and `FFprobe` to a system-wide location such as `C:\Program Files\FFmpeg`, select and edit the `Path` variable under the "System variables" heading. Else, if you installed them to some place specific to your user account, edit the `Path` variable under the "User variables for " heading. +5. If you installed `FFmpeg` and `FFprobe` to a system-wide location such as `C:\Program Files\FFmpeg`, select and edit the `Path` variable under the "System variables" heading. Else, if you installed them to some place specific to your user account, edit the `Path` variable under the "User variables for \" heading. ![Environment Variables screenshot](/img/docs/environment_variables.png) diff --git a/packages/documentation/versioned_sidebars/version-1.50.0-sidebars.json b/packages/documentation/versioned_sidebars/version-1.50.0-sidebars.json new file mode 100644 index 0000000000..d7c19231b4 --- /dev/null +++ b/packages/documentation/versioned_sidebars/version-1.50.0-sidebars.json @@ -0,0 +1,14 @@ +{ + "userGuide": [ + { + "type": "autogenerated", + "dirName": "user-guide" + } + ], + "forDevelopers": [ + { + "type": "autogenerated", + "dirName": "for-developers" + } + ] +} From 13f055601b9aba2d2d233e2fa29b5d19ab9d8ffc Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 29 Nov 2024 18:08:49 +0100 Subject: [PATCH 29/30] chore: improve documentation --- .../lib/ReactMeteorData/ReactMeteorData.tsx | 63 ++++++++++++------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx b/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx index efe17b7371..10257bcea9 100644 --- a/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx +++ b/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx @@ -372,43 +372,58 @@ export function useTracker( return meteorData } -function useReadyState(): { - ready: boolean - setReady: (value: boolean) => void - cancelPreviousReady: (timeout: number) => void +/** + * A hook to track a boolean state with a sort of histeresis, with preference for `true`. `setState` makes the returned + * `state` be `true` immediately, but `false` only after `resetState` is called and `timeout` elapses. If `setState` + * is called with `true` before `timeout` elapses, then `resetState` is aborted and `state` will remain `ture. + * + * Later `resetState` calls replace earlier unelapsed calls and their timeout periods. + * + * @param {boolean} [initialState=false] + * @return {*} {{ + * state: boolean + * setState: (value: boolean) => void + * resetState: (timeout: number) => void + * }} + */ +function useDelayState(initialState = false): { + state: boolean + setState: (value: boolean) => void + resetState: (timeout: number) => void } { - const [ready, setReady] = useState(false) - const [prevReady, setPrevReady] = useState(false) + const [state, setState] = useState(initialState) + const [prevState, setPrevState] = useState(initialState) const prevReadyTimeoutRef = useRef(null) - const setIsReady = useCallback( + const setStateAndClearResets = useCallback( (value: boolean) => { - setReady(value) + setState(value) if (value) { - setPrevReady(true) + setPrevState(true) if (prevReadyTimeoutRef.current !== null) { window.clearTimeout(prevReadyTimeoutRef.current) prevReadyTimeoutRef.current = null } } }, - [setReady, setPrevReady] + [setState, setPrevState] ) - const cancelPrevReady = useCallback( - (timeout: number) => { - prevReadyTimeoutRef.current = window.setTimeout(() => { - setPrevReady(false) - }, timeout) - }, - [prevReadyTimeoutRef] - ) + const resetStateAfterDelay = useCallback((timeout: number) => { + if (prevReadyTimeoutRef.current !== null) { + window.clearTimeout(prevReadyTimeoutRef.current) + } + prevReadyTimeoutRef.current = window.setTimeout(() => { + prevReadyTimeoutRef.current = null + setPrevState(false) + }, timeout) + }, []) return { - ready: ready || prevReady, - setReady: setIsReady, - cancelPreviousReady: cancelPrevReady, + state: state || prevState, + setState: setStateAndClearResets, + resetState: resetStateAfterDelay, } } @@ -425,7 +440,7 @@ export function useSubscription( sub: K, ...args: Parameters ): boolean { - const { ready, setReady, cancelPreviousReady } = useReadyState() + const { state: ready, setState: setReady, resetState: cancelPreviousReady } = useDelayState() useEffect(() => { const subscription = Tracker.nonreactive(() => meteorSubscribe(sub, ...args)) @@ -465,7 +480,7 @@ export function useSubscriptionIfEnabled( enable: boolean, ...args: Parameters ): boolean { - const { ready, setReady, cancelPreviousReady } = useReadyState() + const { state: ready, setState: setReady, resetState: cancelPreviousReady } = useDelayState() useEffect(() => { if (!enable) { @@ -510,7 +525,7 @@ export function useSubscriptionIfEnabledReadyOnce ): boolean { - const { ready, setReady, cancelPreviousReady } = useReadyState() + const { state: ready, setState: setReady, resetState: cancelPreviousReady } = useDelayState() useEffect(() => { if (!enable) { From d2a3cdf425d49e40345537c62a97f635d1d1261e Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Wed, 4 Dec 2024 11:16:09 +0100 Subject: [PATCH 30/30] chore(release): 1.51.4 --- meteor/CHANGELOG.md | 10 +++++ meteor/package.json | 2 +- meteor/yarn.lock | 12 +++--- packages/blueprints-integration/CHANGELOG.md | 8 ++++ packages/blueprints-integration/package.json | 4 +- packages/corelib/package.json | 6 +-- packages/documentation/package.json | 2 +- packages/job-worker/package.json | 8 ++-- packages/lerna.json | 2 +- packages/live-status-gateway/package.json | 10 ++--- packages/mos-gateway/CHANGELOG.md | 8 ++++ packages/mos-gateway/package.json | 6 +-- packages/openapi/package.json | 2 +- packages/playout-gateway/CHANGELOG.md | 8 ++++ packages/playout-gateway/package.json | 6 +-- packages/server-core-integration/CHANGELOG.md | 8 ++++ packages/server-core-integration/package.json | 4 +- packages/shared-lib/package.json | 2 +- packages/yarn.lock | 38 +++++++++---------- 19 files changed, 94 insertions(+), 52 deletions(-) diff --git a/meteor/CHANGELOG.md b/meteor/CHANGELOG.md index be59164e1b..e4498ae87c 100644 --- a/meteor/CHANGELOG.md +++ b/meteor/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [1.51.4](///compare/v1.51.3...v1.51.4) (2024-12-04) + + +### Bug Fixes + +* Device Action Studio Context gets lost, Adlib previews are unstable 193815d +* Live Status Gateway Dockerfile (regular) still uses yarn to start 0ae53c4 +* release scripts broken on Windows 9636051 +* RundownView shows spinner when unMOSing a Rundown from a Playlist 874e85c + ### [1.51.2](https://github.com/nrkno/tv-automation-server-core/compare/v1.51.1...v1.51.2) (2024-11-21) diff --git a/meteor/package.json b/meteor/package.json index 3e27c5e714..91f635f3a0 100644 --- a/meteor/package.json +++ b/meteor/package.json @@ -1,6 +1,6 @@ { "name": "automation-core", - "version": "1.51.3", + "version": "1.51.4", "private": true, "engines": { "node": ">=14.19.1" diff --git a/meteor/yarn.lock b/meteor/yarn.lock index a6f56b2e2b..c22865dcff 100644 --- a/meteor/yarn.lock +++ b/meteor/yarn.lock @@ -1321,7 +1321,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@portal:../packages/blueprints-integration::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/shared-lib": 1.51.4 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: node @@ -1362,8 +1362,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/corelib@portal:../packages/corelib::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/blueprints-integration": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/blueprints-integration": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -1394,9 +1394,9 @@ __metadata: resolution: "@sofie-automation/job-worker@portal:../packages/job-worker::locator=automation-core%40workspace%3A." dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.3 - "@sofie-automation/corelib": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/blueprints-integration": 1.51.4 + "@sofie-automation/corelib": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 diff --git a/packages/blueprints-integration/CHANGELOG.md b/packages/blueprints-integration/CHANGELOG.md index abf1b45e2d..4105116d47 100644 --- a/packages/blueprints-integration/CHANGELOG.md +++ b/packages/blueprints-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) + +**Note:** Version bump only for package @sofie-automation/blueprints-integration + + + + + ## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) **Note:** Version bump only for package @sofie-automation/blueprints-integration diff --git a/packages/blueprints-integration/package.json b/packages/blueprints-integration/package.json index fc71da3f4f..2af513ab05 100644 --- a/packages/blueprints-integration/package.json +++ b/packages/blueprints-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/blueprints-integration", - "version": "1.51.3", + "version": "1.51.4", "description": "Library to define the interaction between core and the blueprints.", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -38,7 +38,7 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/shared-lib": "1.51.4", "tslib": "^2.6.2", "type-fest": "^3.13.1" }, diff --git a/packages/corelib/package.json b/packages/corelib/package.json index 4ac419dab0..1be22fa65f 100644 --- a/packages/corelib/package.json +++ b/packages/corelib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/corelib", - "version": "1.51.3", + "version": "1.51.4", "private": true, "description": "Internal library for some types shared by core and workers", "main": "dist/index.js", @@ -39,8 +39,8 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.3", - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/blueprints-integration": "1.51.4", + "@sofie-automation/shared-lib": "1.51.4", "fast-clone": "^1.5.13", "i18next": "^21.10.0", "influx": "^5.9.3", diff --git a/packages/documentation/package.json b/packages/documentation/package.json index 3e30e7ac85..28ad6a1d6b 100644 --- a/packages/documentation/package.json +++ b/packages/documentation/package.json @@ -1,6 +1,6 @@ { "name": "sofie-documentation", - "version": "1.51.3", + "version": "1.51.4", "private": true, "scripts": { "docusaurus": "docusaurus", diff --git a/packages/job-worker/package.json b/packages/job-worker/package.json index bbac4c7c60..bbb939e723 100644 --- a/packages/job-worker/package.json +++ b/packages/job-worker/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/job-worker", - "version": "1.51.3", + "version": "1.51.4", "description": "Worker for things", "main": "dist/index.js", "license": "MIT", @@ -41,9 +41,9 @@ ], "dependencies": { "@slack/webhook": "^6.1.0", - "@sofie-automation/blueprints-integration": "1.51.3", - "@sofie-automation/corelib": "1.51.3", - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/blueprints-integration": "1.51.4", + "@sofie-automation/corelib": "1.51.4", + "@sofie-automation/shared-lib": "1.51.4", "amqplib": "^0.10.3", "deepmerge": "^4.3.1", "elastic-apm-node": "^3.51.0", diff --git a/packages/lerna.json b/packages/lerna.json index 74b8a3c69c..3aee830fb3 100644 --- a/packages/lerna.json +++ b/packages/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.51.3", + "version": "1.51.4", "npmClient": "yarn", "useWorkspaces": true } diff --git a/packages/live-status-gateway/package.json b/packages/live-status-gateway/package.json index 4397d3b2f3..0cd6b534b4 100644 --- a/packages/live-status-gateway/package.json +++ b/packages/live-status-gateway/package.json @@ -1,6 +1,6 @@ { "name": "live-status-gateway", - "version": "1.51.3", + "version": "1.51.4", "private": true, "description": "Provides state from Sofie over sockets", "license": "MIT", @@ -53,10 +53,10 @@ "production" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.3", - "@sofie-automation/corelib": "1.51.3", - "@sofie-automation/server-core-integration": "1.51.3", - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/blueprints-integration": "1.51.4", + "@sofie-automation/corelib": "1.51.4", + "@sofie-automation/server-core-integration": "1.51.4", + "@sofie-automation/shared-lib": "1.51.4", "debug": "^4.3.4", "fast-clone": "^1.5.13", "influx": "^5.9.3", diff --git a/packages/mos-gateway/CHANGELOG.md b/packages/mos-gateway/CHANGELOG.md index 9a91703d98..12651308e8 100644 --- a/packages/mos-gateway/CHANGELOG.md +++ b/packages/mos-gateway/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) + +**Note:** Version bump only for package mos-gateway + + + + + ## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) diff --git a/packages/mos-gateway/package.json b/packages/mos-gateway/package.json index e0085ca549..d8c3461b16 100644 --- a/packages/mos-gateway/package.json +++ b/packages/mos-gateway/package.json @@ -1,6 +1,6 @@ { "name": "mos-gateway", - "version": "1.51.3", + "version": "1.51.4", "private": true, "description": "MOS-Gateway for the Sofie project", "license": "MIT", @@ -66,8 +66,8 @@ ], "dependencies": { "@mos-connection/connector": "4.1.1", - "@sofie-automation/server-core-integration": "1.51.3", - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/server-core-integration": "1.51.4", + "@sofie-automation/shared-lib": "1.51.4", "tslib": "^2.6.2", "type-fest": "^3.13.1", "underscore": "^1.13.6", diff --git a/packages/openapi/package.json b/packages/openapi/package.json index a79735ff45..4f9e693cc6 100644 --- a/packages/openapi/package.json +++ b/packages/openapi/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/openapi", - "version": "1.51.3", + "version": "1.51.4", "license": "MIT", "repository": { "type": "git", diff --git a/packages/playout-gateway/CHANGELOG.md b/packages/playout-gateway/CHANGELOG.md index 560b526971..0396e96547 100644 --- a/packages/playout-gateway/CHANGELOG.md +++ b/packages/playout-gateway/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) + +**Note:** Version bump only for package playout-gateway + + + + + ## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) diff --git a/packages/playout-gateway/package.json b/packages/playout-gateway/package.json index 0d8e33c4fa..77702d6d29 100644 --- a/packages/playout-gateway/package.json +++ b/packages/playout-gateway/package.json @@ -1,6 +1,6 @@ { "name": "playout-gateway", - "version": "1.51.3", + "version": "1.51.4", "private": true, "description": "Connect to Core, play stuff", "license": "MIT", @@ -56,8 +56,8 @@ "production" ], "dependencies": { - "@sofie-automation/server-core-integration": "1.51.3", - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/server-core-integration": "1.51.4", + "@sofie-automation/shared-lib": "1.51.4", "debug": "^4.3.4", "influx": "^5.9.3", "timeline-state-resolver": "9.2.1", diff --git a/packages/server-core-integration/CHANGELOG.md b/packages/server-core-integration/CHANGELOG.md index 7dfd8d5ce6..b259defec9 100644 --- a/packages/server-core-integration/CHANGELOG.md +++ b/packages/server-core-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) + +**Note:** Version bump only for package @sofie-automation/server-core-integration + + + + + ## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) **Note:** Version bump only for package @sofie-automation/server-core-integration diff --git a/packages/server-core-integration/package.json b/packages/server-core-integration/package.json index 954e9f8f04..e8be09e879 100644 --- a/packages/server-core-integration/package.json +++ b/packages/server-core-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/server-core-integration", - "version": "1.51.3", + "version": "1.51.4", "description": "Library for connecting to Core", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -70,7 +70,7 @@ "production" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/shared-lib": "1.51.4", "ejson": "^2.2.3", "eventemitter3": "^4.0.7", "faye-websocket": "^0.11.4", diff --git a/packages/shared-lib/package.json b/packages/shared-lib/package.json index 22e2b6b7fc..60928b7eaa 100644 --- a/packages/shared-lib/package.json +++ b/packages/shared-lib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/shared-lib", - "version": "1.51.3", + "version": "1.51.4", "description": "Library for types & values shared by core, workers and gateways", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/packages/yarn.lock b/packages/yarn.lock index cf52fe25db..2cd2a6209b 100644 --- a/packages/yarn.lock +++ b/packages/yarn.lock @@ -4565,11 +4565,11 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/blueprints-integration@1.51.3, @sofie-automation/blueprints-integration@workspace:blueprints-integration": +"@sofie-automation/blueprints-integration@1.51.4, @sofie-automation/blueprints-integration@workspace:blueprints-integration": version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@workspace:blueprints-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/shared-lib": 1.51.4 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: unknown @@ -4606,12 +4606,12 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/corelib@1.51.3, @sofie-automation/corelib@workspace:corelib": +"@sofie-automation/corelib@1.51.4, @sofie-automation/corelib@workspace:corelib": version: 0.0.0-use.local resolution: "@sofie-automation/corelib@workspace:corelib" dependencies: - "@sofie-automation/blueprints-integration": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/blueprints-integration": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -4642,9 +4642,9 @@ __metadata: resolution: "@sofie-automation/job-worker@workspace:job-worker" dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.3 - "@sofie-automation/corelib": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/blueprints-integration": 1.51.4 + "@sofie-automation/corelib": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 @@ -4674,11 +4674,11 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/server-core-integration@1.51.3, @sofie-automation/server-core-integration@workspace:server-core-integration": +"@sofie-automation/server-core-integration@1.51.4, @sofie-automation/server-core-integration@workspace:server-core-integration": version: 0.0.0-use.local resolution: "@sofie-automation/server-core-integration@workspace:server-core-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/shared-lib": 1.51.4 ejson: ^2.2.3 eventemitter3: ^4.0.7 faye-websocket: ^0.11.4 @@ -4688,7 +4688,7 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/shared-lib@1.51.3, @sofie-automation/shared-lib@workspace:shared-lib": +"@sofie-automation/shared-lib@1.51.4, @sofie-automation/shared-lib@workspace:shared-lib": version: 0.0.0-use.local resolution: "@sofie-automation/shared-lib@workspace:shared-lib" dependencies: @@ -15334,10 +15334,10 @@ asn1@evs-broadcast/node-asn1: "@asyncapi/generator": ^1.17.25 "@asyncapi/html-template": ^2.3.9 "@asyncapi/nodejs-ws-template": ^0.9.36 - "@sofie-automation/blueprints-integration": 1.51.3 - "@sofie-automation/corelib": 1.51.3 - "@sofie-automation/server-core-integration": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/blueprints-integration": 1.51.4 + "@sofie-automation/corelib": 1.51.4 + "@sofie-automation/server-core-integration": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 debug: ^4.3.4 fast-clone: ^1.5.13 influx: ^5.9.3 @@ -17410,8 +17410,8 @@ asn1@evs-broadcast/node-asn1: resolution: "mos-gateway@workspace:mos-gateway" dependencies: "@mos-connection/connector": 4.1.1 - "@sofie-automation/server-core-integration": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/server-core-integration": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 tslib: ^2.6.2 type-fest: ^3.13.1 underscore: ^1.13.6 @@ -19397,8 +19397,8 @@ asn1@evs-broadcast/node-asn1: version: 0.0.0-use.local resolution: "playout-gateway@workspace:playout-gateway" dependencies: - "@sofie-automation/server-core-integration": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/server-core-integration": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 debug: ^4.3.4 influx: ^5.9.3 timeline-state-resolver: 9.2.1