Skip to content

Commit

Permalink
Merge pull request #1382 from nrkno/fix/sofie-3665/infinite-adLibs-no…
Browse files Browse the repository at this point in the history
…t-denowified

fix(Playout): infinite AdLib Items' timeline objects are not denowified (SOFIE-3665)
  • Loading branch information
jstarpl authored Feb 6, 2025
2 parents 0032cea + 5469a1a commit 608dd27
Showing 1 changed file with 76 additions and 2 deletions.
78 changes: 76 additions & 2 deletions packages/job-worker/src/playout/timeline/multi-gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { TimelineObjRundown } from '@sofie-automation/corelib/dist/dataModel/Tim
import { normalizeArray } from '@sofie-automation/corelib/dist/lib'
import { PieceTimelineMetadata } from './pieceGroup'
import { StudioPlayoutModelBase } from '../../studio/model/StudioPlayoutModel'
import { logger } from '../../logging'
import { JobContext } from '../../jobs'
import { getCurrentTime } from '../../lib'
import { PlayoutModel } from '../model/PlayoutModel'
Expand Down Expand Up @@ -46,7 +47,7 @@ export function deNowifyMultiGatewayTimeline(
playoutModel.nextPartInstance
)

deNowifyCurrentPieces(
const { objectsNotDeNowified } = deNowifyCurrentPieces(
targetNowTime,
timingContext,
currentPartInstance,
Expand All @@ -55,6 +56,9 @@ export function deNowifyMultiGatewayTimeline(
)

updatePlannedTimingsForPieceInstances(playoutModel, currentPartInstance, partGroupTimings, timelineObjsMap)

// Because updatePlannedTimingsForPieceInstances changes start times of infinites, we can now run deNowifyInfinites()
deNowifyInfinites(targetNowTime, objectsNotDeNowified, timelineObjsMap)
}

/**
Expand Down Expand Up @@ -142,16 +146,83 @@ function updatePartInstancePlannedTimes(
}
}

/**
* Replace the `now` time in any timeline objects in freshly-placed infinites.
*
* This is effectively only needed when a new item has been placed on the timeline just now and changes made by
* `updatePlannedTimingsForPieceInstances` haven't been taken into account when generating the timeline. On the next
* regeneration, items will already use the timestamps persited by `updatePlannedTimingsForPieceInstances` and will not
* be included in `infiniteObjs`.
*/
function deNowifyInfinites(
targetNowTime: number,
/** A list of objects that need to be updated */
infiniteObjs: TimelineObjRundown[],
timelineObjsMap: Record<string, TimelineObjRundown>
) {
/**
* Recursively look up the absolute starttime of a timeline object
* taking into account its parent's times.
* Note: This only supports timeline objects that have absolute enable.start times.
*/
const getStartTime = (obj: TimelineObjRundown): number | undefined => {
if (Array.isArray(obj.enable)) return undefined

const myStartTime = typeof obj.enable.start === 'number' ? obj.enable.start : undefined

if (!obj.inGroup) return myStartTime

if (myStartTime === undefined) return undefined

const parentObject = timelineObjsMap[obj.inGroup]
if (!parentObject) return undefined

const parentStartTime = getStartTime(parentObject)
if (parentStartTime === undefined) return undefined

return parentStartTime + myStartTime
}

for (const obj of infiniteObjs) {
if (Array.isArray(obj.enable) || obj.enable.start !== 'now') continue

if (!obj.inGroup) {
obj.enable = { start: targetNowTime }
continue
}

const parentObject = timelineObjsMap[obj.inGroup]
if (!parentObject) {
logger.error(`deNowifyInfinites: Parent obj "${obj.inGroup}" not found of object "${obj.id}"`)
continue
}

const parentStartTime = getStartTime(parentObject)
if (parentStartTime === undefined) {
logger.error(
`deNowifyInfinites: Unable to derive an absolute start time of parent "${obj.inGroup}" for object "${obj.id}"`
)
continue
}

obj.enable = { start: targetNowTime - parentStartTime }
logger.silly(
`deNowifyInfinites: Setting "${obj.id}" enable.start = ${obj.enable.start}, ${targetNowTime} ${parentStartTime} parentObject: "${parentObject.id}"`
)
}
}
/**
* Replace the `now` time in any Pieces on the timeline from the current Part with concrete start times
* @returns a list of object that couldn't be updated at this time.
*/
function deNowifyCurrentPieces(
targetNowTime: number,
timingContext: RundownTimelineTimingContext,
currentPartInstance: PlayoutPartInstanceModel,
currentPartGroupStartTime: number,
timelineObjsMap: Record<string, TimelineObjRundown>
) {
): { objectsNotDeNowified: TimelineObjRundown[] } {
const objectsNotDeNowified: TimelineObjRundown[] = []
// The relative time for 'now' to be resolved to, inside of the part group
const nowInPart = targetNowTime - currentPartGroupStartTime

Expand All @@ -176,6 +247,8 @@ function deNowifyCurrentPieces(
obj.enable = { start: nowInPart }
} else if (!obj.inGroup) {
obj.enable = { start: targetNowTime }
} else {
objectsNotDeNowified.push(obj)
}
}
}
Expand Down Expand Up @@ -203,6 +276,7 @@ function deNowifyCurrentPieces(
}
}
}
return { objectsNotDeNowified }
}

function updatePlannedTimingsForPieceInstances(
Expand Down

0 comments on commit 608dd27

Please sign in to comment.