Skip to content

Commit 608dd27

Browse files
authored
Merge pull request #1382 from nrkno/fix/sofie-3665/infinite-adLibs-not-denowified
fix(Playout): infinite AdLib Items' timeline objects are not denowified (SOFIE-3665)
2 parents 0032cea + 5469a1a commit 608dd27

File tree

1 file changed

+76
-2
lines changed

1 file changed

+76
-2
lines changed

packages/job-worker/src/playout/timeline/multi-gateway.ts

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { TimelineObjRundown } from '@sofie-automation/corelib/dist/dataModel/Tim
55
import { normalizeArray } from '@sofie-automation/corelib/dist/lib'
66
import { PieceTimelineMetadata } from './pieceGroup'
77
import { StudioPlayoutModelBase } from '../../studio/model/StudioPlayoutModel'
8+
import { logger } from '../../logging'
89
import { JobContext } from '../../jobs'
910
import { getCurrentTime } from '../../lib'
1011
import { 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,83 @@ function updatePartInstancePlannedTimes(
142146
}
143147
}
144148

149+
/**
150+
* Replace the `now` time in any timeline objects in freshly-placed infinites.
151+
*
152+
* This is effectively only needed when a new item has been placed on the timeline just now and changes made by
153+
* `updatePlannedTimingsForPieceInstances` haven't been taken into account when generating the timeline. On the next
154+
* regeneration, items will already use the timestamps persited by `updatePlannedTimingsForPieceInstances` and will not
155+
* be included in `infiniteObjs`.
156+
*/
157+
function deNowifyInfinites(
158+
targetNowTime: number,
159+
/** A list of objects that need to be updated */
160+
infiniteObjs: TimelineObjRundown[],
161+
timelineObjsMap: Record<string, TimelineObjRundown>
162+
) {
163+
/**
164+
* Recursively look up the absolute starttime of a timeline object
165+
* taking into account its parent's times.
166+
* Note: This only supports timeline objects that have absolute enable.start times.
167+
*/
168+
const getStartTime = (obj: TimelineObjRundown): number | undefined => {
169+
if (Array.isArray(obj.enable)) return undefined
170+
171+
const myStartTime = typeof obj.enable.start === 'number' ? obj.enable.start : undefined
172+
173+
if (!obj.inGroup) return myStartTime
174+
175+
if (myStartTime === undefined) return undefined
176+
177+
const parentObject = timelineObjsMap[obj.inGroup]
178+
if (!parentObject) return undefined
179+
180+
const parentStartTime = getStartTime(parentObject)
181+
if (parentStartTime === undefined) return undefined
182+
183+
return parentStartTime + myStartTime
184+
}
185+
186+
for (const obj of infiniteObjs) {
187+
if (Array.isArray(obj.enable) || obj.enable.start !== 'now') continue
188+
189+
if (!obj.inGroup) {
190+
obj.enable = { start: targetNowTime }
191+
continue
192+
}
193+
194+
const parentObject = timelineObjsMap[obj.inGroup]
195+
if (!parentObject) {
196+
logger.error(`deNowifyInfinites: Parent obj "${obj.inGroup}" not found of object "${obj.id}"`)
197+
continue
198+
}
199+
200+
const parentStartTime = getStartTime(parentObject)
201+
if (parentStartTime === undefined) {
202+
logger.error(
203+
`deNowifyInfinites: Unable to derive an absolute start time of parent "${obj.inGroup}" for object "${obj.id}"`
204+
)
205+
continue
206+
}
207+
208+
obj.enable = { start: targetNowTime - parentStartTime }
209+
logger.silly(
210+
`deNowifyInfinites: Setting "${obj.id}" enable.start = ${obj.enable.start}, ${targetNowTime} ${parentStartTime} parentObject: "${parentObject.id}"`
211+
)
212+
}
213+
}
145214
/**
146215
* Replace the `now` time in any Pieces on the timeline from the current Part with concrete start times
216+
* @returns a list of object that couldn't be updated at this time.
147217
*/
148218
function deNowifyCurrentPieces(
149219
targetNowTime: number,
150220
timingContext: RundownTimelineTimingContext,
151221
currentPartInstance: PlayoutPartInstanceModel,
152222
currentPartGroupStartTime: number,
153223
timelineObjsMap: Record<string, TimelineObjRundown>
154-
) {
224+
): { objectsNotDeNowified: TimelineObjRundown[] } {
225+
const objectsNotDeNowified: TimelineObjRundown[] = []
155226
// The relative time for 'now' to be resolved to, inside of the part group
156227
const nowInPart = targetNowTime - currentPartGroupStartTime
157228

@@ -176,6 +247,8 @@ function deNowifyCurrentPieces(
176247
obj.enable = { start: nowInPart }
177248
} else if (!obj.inGroup) {
178249
obj.enable = { start: targetNowTime }
250+
} else {
251+
objectsNotDeNowified.push(obj)
179252
}
180253
}
181254
}
@@ -203,6 +276,7 @@ function deNowifyCurrentPieces(
203276
}
204277
}
205278
}
279+
return { objectsNotDeNowified }
206280
}
207281

208282
function updatePlannedTimingsForPieceInstances(

0 commit comments

Comments
 (0)