@@ -5,6 +5,7 @@ import { TimelineObjRundown } from '@sofie-automation/corelib/dist/dataModel/Tim
55import { normalizeArray } from '@sofie-automation/corelib/dist/lib'
66import { PieceTimelineMetadata } from './pieceGroup'
77import { StudioPlayoutModelBase } from '../../studio/model/StudioPlayoutModel'
8+ import { logger } from '../../logging'
89import { JobContext } from '../../jobs'
910import { getCurrentTime } from '../../lib'
1011import { PlayoutModel } from '../model/PlayoutModel'
@@ -46,7 +47,7 @@ export function deNowifyMultiGatewayTimeline(
4647 playoutModel . nextPartInstance
4748 )
4849
49- deNowifyCurrentPieces (
50+ const { objectsNotDeNowified } = deNowifyCurrentPieces (
5051 targetNowTime ,
5152 timingContext ,
5253 currentPartInstance ,
@@ -55,6 +56,9 @@ export function deNowifyMultiGatewayTimeline(
5556 )
5657
5758 updatePlannedTimingsForPieceInstances ( playoutModel , currentPartInstance , partGroupTimings , timelineObjsMap )
59+
60+ // Because updatePlannedTimingsForPieceInstances changes start times of infinites, we can now run deNowifyInfinites()
61+ deNowifyInfinites ( targetNowTime , objectsNotDeNowified , timelineObjsMap )
5862}
5963
6064/**
@@ -142,16 +146,75 @@ function updatePartInstancePlannedTimes(
142146 }
143147}
144148
149+ /**
150+ * Replace the `now` time in any timeline objects in infinites
151+ */
152+ function deNowifyInfinites (
153+ targetNowTime : number ,
154+ /** A list of objects that need to be updated */
155+ infiniteObjs : TimelineObjRundown [ ] ,
156+ timelineObjsMap : Record < string , TimelineObjRundown >
157+ ) {
158+ /**
159+ * Recursively look up the absolute starttime of a timeline object
160+ * taking into account its parent's times.
161+ * Note: This only supports timeline objects that have absolute enable.start times.
162+ */
163+ const getStartTime = ( obj : TimelineObjRundown ) : number | undefined => {
164+ if ( Array . isArray ( obj . enable ) ) return undefined
165+
166+ const myStartTime = typeof obj . enable . start === 'number' ? obj . enable . start : undefined
167+
168+ if ( ! obj . inGroup ) return myStartTime
169+
170+ if ( myStartTime === undefined ) return undefined
171+
172+ const parentObject = timelineObjsMap [ obj . inGroup ]
173+ if ( ! parentObject ) return undefined
174+
175+ const parentStartTime = getStartTime ( parentObject )
176+ if ( parentStartTime === undefined ) return undefined
177+
178+ return parentStartTime + myStartTime
179+ }
180+
181+ for ( const obj of infiniteObjs ) {
182+ if ( ! Array . isArray ( obj . enable ) && obj . enable . start === 'now' ) {
183+ if ( obj . inGroup ) {
184+ const parentObject = timelineObjsMap [ obj . inGroup ]
185+ if ( parentObject ) {
186+ const parentStartTime = getStartTime ( parentObject )
187+ if ( parentStartTime !== undefined ) {
188+ obj . enable = { start : targetNowTime - parentStartTime }
189+ } else {
190+ logger . error (
191+ `Unable to derive an absolute start time of parent "${ obj . inGroup } " for object "${ obj . id } " during deNowifyInfinites`
192+ )
193+ }
194+ } else {
195+ logger . error ( `Parent obj "${ obj . inGroup } " not found of object "${ obj . id } " during deNowifyInfinites` )
196+ }
197+ } else {
198+ logger . error (
199+ `Unexpected "now" time during deNowifyInfinites, setting to absolute time for a timelineObject not inGroup: "${ obj . id } "`
200+ )
201+ obj . enable = { start : targetNowTime }
202+ }
203+ }
204+ }
205+ }
145206/**
146207 * Replace the `now` time in any Pieces on the timeline from the current Part with concrete start times
208+ * @returns a list of object that couldn't be updated at this time.
147209 */
148210function deNowifyCurrentPieces (
149211 targetNowTime : number ,
150212 timingContext : RundownTimelineTimingContext ,
151213 currentPartInstance : PlayoutPartInstanceModel ,
152214 currentPartGroupStartTime : number ,
153215 timelineObjsMap : Record < string , TimelineObjRundown >
154- ) {
216+ ) : { objectsNotDeNowified : TimelineObjRundown [ ] } {
217+ const objectsNotDeNowified : TimelineObjRundown [ ] = [ ]
155218 // The relative time for 'now' to be resolved to, inside of the part group
156219 const nowInPart = targetNowTime - currentPartGroupStartTime
157220
@@ -176,6 +239,8 @@ function deNowifyCurrentPieces(
176239 obj . enable = { start : nowInPart }
177240 } else if ( ! obj . inGroup ) {
178241 obj . enable = { start : targetNowTime }
242+ } else {
243+ objectsNotDeNowified . push ( obj )
179244 }
180245 }
181246 }
@@ -203,6 +268,7 @@ function deNowifyCurrentPieces(
203268 }
204269 }
205270 }
271+ return { objectsNotDeNowified }
206272}
207273
208274function updatePlannedTimingsForPieceInstances (
0 commit comments