Skip to content

Commit 6b28489

Browse files
authored
Merge pull request Sofie-Automation#1480 from evs-broadcast/feat/persist-infinite-adlibs
2 parents 81e240e + 7a27c3c commit 6b28489

File tree

19 files changed

+92
-14
lines changed

19 files changed

+92
-14
lines changed

meteor/server/api/rest/v1/typeConversion.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ export function studioSettingsFrom(apiStudioSettings: APIStudioSettings): Comple
384384
multiGatewayNowSafeLatency: apiStudioSettings.multiGatewayNowSafeLatency,
385385
allowRundownResetOnAir: apiStudioSettings.allowRundownResetOnAir,
386386
preserveOrphanedSegmentPositionInRundown: apiStudioSettings.preserveOrphanedSegmentPositionInRundown,
387+
allowTestingAdlibsToPersist: apiStudioSettings.allowTestingAdlibsToPersist,
387388
minimumTakeSpan: apiStudioSettings.minimumTakeSpan ?? DEFAULT_MINIMUM_TAKE_SPAN,
388389
enableQuickLoop: apiStudioSettings.enableQuickLoop,
389390
forceQuickLoopAutoNext: forceQuickLoopAutoNextFrom(apiStudioSettings.forceQuickLoopAutoNext),
@@ -416,6 +417,7 @@ export function APIStudioSettingsFrom(settings: IStudioSettings): Complete<APISt
416417
fallbackPartDuration: settings.fallbackPartDuration,
417418
enableUserEdits: settings.enableUserEdits,
418419
allowAdlibTestingSegment: settings.allowAdlibTestingSegment,
420+
allowTestingAdlibsToPersist: settings.allowTestingAdlibsToPersist,
419421
allowHold: settings.allowHold,
420422
allowPieceDirectPlay: settings.allowPieceDirectPlay,
421423
enableBuckets: settings.enableBuckets,

meteor/server/lib/rest/v1/studios.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ export interface APIStudioSettings {
218218
fallbackPartDuration?: number
219219
enableUserEdits?: boolean
220220
allowAdlibTestingSegment?: boolean
221+
allowTestingAdlibsToPersist?: boolean
221222
allowHold?: boolean
222223
allowPieceDirectPlay?: boolean
223224
enableBuckets?: boolean

packages/corelib/src/playout/__tests__/infinites.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ describe('Infinites', () => {
3535
segment,
3636
newInstanceId,
3737
true,
38+
false,
3839
false
3940
)
4041
return resolvedInstances.map((p) => ({

packages/corelib/src/playout/infinites.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,11 @@ export function getPlayheadTrackingInfinitesForPart(
103103
intoSegment: ReadonlyDeep<Pick<DBSegment, '_id' | 'orphaned'>>,
104104
newInstanceId: PartInstanceId,
105105
nextPartIsAfterCurrentPart: boolean,
106-
isTemporary: boolean
106+
isTemporary: boolean,
107+
allowTestingAdlibsToPersist: boolean
107108
): PieceInstance[] {
108109
if (
110+
!allowTestingAdlibsToPersist &&
109111
intoSegment._id !== playingSegment._id &&
110112
(intoSegment.orphaned === SegmentOrphanedReason.ADLIB_TESTING ||
111113
playingSegment.orphaned === SegmentOrphanedReason.ADLIB_TESTING)
@@ -210,7 +212,10 @@ export function getPlayheadTrackingInfinitesForPart(
210212
isValid =
211213
candidatePiece.rundownId === intoPart.rundownId &&
212214
(segmentsToReceiveOnRundownEndFromSet.has(currentPartInstance.segmentId) ||
213-
currentPartInstance.segmentId === intoPart.segmentId)
215+
currentPartInstance.segmentId === intoPart.segmentId ||
216+
// If infinites are allowed to persist, then the infinite is allowed to continue
217+
(allowTestingAdlibsToPersist &&
218+
intoSegment.orphaned === SegmentOrphanedReason.ADLIB_TESTING))
214219
break
215220
case PieceLifespan.OutOnShowStyleEnd:
216221
isValid = canContinueShowStyleEndInfinites
@@ -380,7 +385,8 @@ export function getPieceInstancesForPart(
380385
orderedPartIds: PartId[],
381386
newInstanceId: PartInstanceId,
382387
nextPartIsAfterCurrentPart: boolean,
383-
isTemporary: boolean
388+
isTemporary: boolean,
389+
allowTestingAdlibsToPersist: boolean
384390
): PieceInstance[] {
385391
const doesPieceAStartBeforePieceB = (
386392
pieceA: ReadonlyDeep<PieceInstancePiece>,
@@ -458,7 +464,8 @@ export function getPieceInstancesForPart(
458464
segment,
459465
newInstanceId,
460466
nextPartIsAfterCurrentPart,
461-
isTemporary
467+
isTemporary,
468+
allowTestingAdlibsToPersist
462469
)
463470
: []
464471

packages/job-worker/src/playout/infinites.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ export async function syncPlayheadInfinitesForNextPartInstance(
278278
nextSegment?.segment,
279279
toPartInstance.partInstance._id,
280280
nextPartIsAfterCurrentPart,
281-
false
281+
false,
282+
context.studio.settings.allowTestingAdlibsToPersist ?? false
282283
)
283284

284285
toPartInstance.replaceInfinitesFromPreviousPlayhead(infinites)
@@ -378,7 +379,8 @@ export function getPieceInstancesForPart(
378379
playoutModel.getAllOrderedParts().map((p) => p._id),
379380
newInstanceId,
380381
nextPartIsAfterCurrentPart,
381-
false
382+
false,
383+
context.studio.settings.allowTestingAdlibsToPersist ?? false
382384
)
383385
if (span) span.end()
384386
return res

packages/openapi/api/definitions/studios.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,9 @@ components:
552552
allowAdlibTestingSegment:
553553
type: boolean
554554
description: Whether to allow adlib testing mode, before a Part is playing in a Playlist
555+
allowTestingAdlibsToPersist:
556+
type: boolean
557+
description: Whether to allow infinite adlib from adlib testing mode to persist in the rundown
555558
allowHold:
556559
type: boolean
557560
description: Whether to allow hold operations for Rundowns in this Studio

packages/shared-lib/src/core/model/StudioSettings.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ export interface IStudioSettings {
4343
/** Preserve unsynced segments position in the rundown, relative to the other segments */
4444
preserveOrphanedSegmentPositionInRundown?: boolean
4545

46+
/** Allow inifite adlibs from adlib testing mode to persist in the rundown */
47+
allowTestingAdlibsToPersist?: boolean
48+
4649
/**
4750
* The minimum amount of time, in milliseconds, that must pass after a take before another take may be performed.
4851
* Default: 1000

packages/webui/src/__mocks__/helpers/database.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
wrapDefaultObject,
2727
} from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
2828
import { UIShowStyleBase } from '@sofie-automation/meteor-lib/dist/api/showStyles'
29+
import { UIStudio } from '@sofie-automation/meteor-lib/dist/api/studios'
2930
import {
3031
BlueprintId,
3132
OrganizationId,
@@ -561,3 +562,13 @@ export function convertToUIShowStyleBase(showStyleBase: DBShowStyleBase): UIShow
561562
outputLayers: applyAndValidateOverrides(showStyleBase.outputLayersWithOverrides).obj,
562563
})
563564
}
565+
export function convertToUIStudio(studio: DBStudio): UIStudio {
566+
return literal<Complete<UIStudio>>({
567+
_id: studio._id,
568+
settings: applyAndValidateOverrides(studio.settingsWithOverrides).obj,
569+
name: studio.name,
570+
routeSets: applyAndValidateOverrides(studio.routeSetsWithOverrides).obj,
571+
routeSetExclusivityGroups: applyAndValidateOverrides(studio.routeSetExclusivityGroupsWithOverrides).obj,
572+
mappings: {},
573+
})
574+
}

packages/webui/src/client/lib/RundownResolver.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ const SIMULATION_INVALIDATION = 3000
108108
* @param {boolean} nextPartIsAfterCurrentPart
109109
* @param {(PartInstance | undefined)} currentPartInstance
110110
* @param {(PieceInstance[] | undefined)} currentPartInstancePieceInstances
111+
* @param {boolean} allowTestingAdlibsToPersist Studio config parameter to allow infinite adlibs from adlib testing to persist in the rundown
111112
* @param {FindOptions<PieceInstance>} [options]
112113
* @param {boolean} [pieceInstanceSimulation] If there are no PieceInstances in the PartInstance, create temporary
113114
* PieceInstances based on the Pieces collection and register a reactive dependancy to recalculate the current
@@ -128,6 +129,7 @@ export function getPieceInstancesForPartInstance(
128129
currentPartInstance: PartInstance | undefined,
129130
currentSegment: Pick<DBSegment, '_id' | 'orphaned'> | undefined,
130131
currentPartInstancePieceInstances: PieceInstance[] | undefined,
132+
allowTestingAdlibsToPersist: boolean,
131133
/** Map of Pieces on Parts, passed through for performance */
132134
allPiecesCache?: Map<PartId, Piece[]>,
133135
options?: FindOptions<PieceInstance>,
@@ -162,7 +164,8 @@ export function getPieceInstancesForPartInstance(
162164
orderedAllParts,
163165
partInstance._id,
164166
nextPartIsAfterCurrentPart,
165-
partInstance.isTemporary
167+
partInstance.isTemporary,
168+
allowTestingAdlibsToPersist
166169
)
167170
} else {
168171
const results =
@@ -209,7 +212,8 @@ export function getPieceInstancesForPartInstance(
209212
orderedAllParts,
210213
partInstance._id,
211214
nextPartIsAfterCurrentPart,
212-
true
215+
true,
216+
allowTestingAdlibsToPersist
213217
)
214218
} else {
215219
// otherwise, return results as they are

packages/webui/src/client/lib/__tests__/rundown.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
DefaultEnvironment,
44
setupDefaultRundownPlaylist,
55
convertToUIShowStyleBase,
6+
convertToUIStudio,
67
} from '../../../__mocks__/helpers/database.js'
78
import { RundownUtils } from '../rundown.js'
89
import { Piece } from '@sofie-automation/corelib/dist/dataModel/Piece'
@@ -16,6 +17,7 @@ import { PartInstances, PieceInstances, Pieces, RundownPlaylists } from '../../c
1617
import { MongoMock } from '../../../__mocks__/mongo.js'
1718
import { RundownPlaylistCollectionUtil } from '../../collections/rundownPlaylistUtil.js'
1819
import { RundownPlaylistClientUtil } from '../rundownPlaylistUtil.js'
20+
import { UIStudio } from '@sofie-automation/meteor-lib/dist/api/studios'
1921

2022
const mockRundownPlaylistsCollection = MongoMock.getInnerMockCollection(RundownPlaylists)
2123
const mockPartInstancesCollection = MongoMock.getInnerMockCollection(PartInstances)
@@ -36,9 +38,11 @@ jest.mock('../../ui/Collections', () => {
3638
describe('client/lib/rundown', () => {
3739
let env: DefaultEnvironment
3840
let playlistId: RundownPlaylistId
41+
let studio: UIStudio
3942
beforeEach(async () => {
4043
env = await setupDefaultStudioEnvironment()
4144
playlistId = (await setupDefaultRundownPlaylist(env)).playlistId
45+
studio = convertToUIStudio(env.studio)
4246
})
4347
describe('RundownUtils.getResolvedSegment', () => {
4448
test('Basic Segment resolution', () => {
@@ -56,6 +60,7 @@ describe('client/lib/rundown', () => {
5660

5761
const resolvedSegment = RundownUtils.getResolvedSegment(
5862
showStyleBase,
63+
studio,
5964
playlist,
6065
rundown,
6166
segment,
@@ -117,6 +122,7 @@ describe('client/lib/rundown', () => {
117122

118123
const resolvedSegment = RundownUtils.getResolvedSegment(
119124
showStyleBase,
125+
studio,
120126
playlist,
121127
rundown,
122128
segment,
@@ -202,6 +208,7 @@ describe('client/lib/rundown', () => {
202208

203209
const resolvedSegment = RundownUtils.getResolvedSegment(
204210
showStyleBase,
211+
studio,
205212
playlist,
206213
rundown,
207214
segment,
@@ -352,6 +359,7 @@ describe('client/lib/rundown', () => {
352359

353360
const resolvedSegment = RundownUtils.getResolvedSegment(
354361
showStyleBase,
362+
studio,
355363
playlist,
356364
rundown,
357365
segment,

0 commit comments

Comments
 (0)