Skip to content

Commit e8826c1

Browse files
author
Mint de Wit
committed
fix: no quickloop autotake on parts that were running for a long time
1 parent f94db28 commit e8826c1

File tree

4 files changed

+79
-6
lines changed

4 files changed

+79
-6
lines changed

meteor/server/publications/lib/quickLoop.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
import { MarkerPosition, compareMarkerPositions } from '@sofie-automation/corelib/dist/playout/playlist'
99
import { ProtectedString, unprotectString } from '@sofie-automation/corelib/dist/protectedString'
1010
import { DEFAULT_FALLBACK_PART_DURATION } from '@sofie-automation/shared-lib/dist/core/constants'
11-
import { generateTranslation } from '../../../lib/lib'
11+
import { generateTranslation, getCurrentTime } from '../../../lib/lib'
1212
import { DBStudio } from '@sofie-automation/corelib/dist/dataModel/Studio'
1313
import { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartInstance'
1414
import { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment'
@@ -48,7 +48,8 @@ export function modifyPartForQuickLoop(
4848
playlist: Pick<DBRundownPlaylist, 'quickLoop'>,
4949
studio: Pick<DBStudio, 'settings'>,
5050
quickLoopStartPosition: MarkerPosition | undefined,
51-
quickLoopEndPosition: MarkerPosition | undefined
51+
quickLoopEndPosition: MarkerPosition | undefined,
52+
canSetAutoNext = () => true
5253
): void {
5354
const partPosition = findPartPosition(part, segmentRanks, rundownRanks)
5455
const isLoopDefined = quickLoopStartPosition && quickLoopEndPosition
@@ -71,9 +72,47 @@ export function modifyPartForQuickLoop(
7172
}
7273
}
7374
}
75+
if (!canSetAutoNext()) return
7476
part.autoNext = part.autoNext || (isLoopingOverriden && (part.expectedDuration ?? 0) > 0)
7577
}
7678

79+
export function modifyPartInstanceForQuickLoop(
80+
partInstance: Omit<DBPartInstance, 'part.privateData'>,
81+
segmentRanks: Record<string, number>,
82+
rundownRanks: Record<string, number>,
83+
playlist: Pick<DBRundownPlaylist, 'quickLoop'>,
84+
studio: Pick<DBStudio, 'settings'>,
85+
quickLoopStartPosition: MarkerPosition | undefined,
86+
quickLoopEndPosition: MarkerPosition | undefined
87+
): void {
88+
// note that the logic for when a part does not do autonext in quickloop should reflect the logic in the QuickLoopService in job worker
89+
const canAutoNext = () => {
90+
const start = partInstance.timings?.plannedStartedPlayback
91+
if (start !== undefined && partInstance.part.expectedDuration) {
92+
// date.now - start = playback duration, duration + offset gives position in part
93+
const playbackDuration = getCurrentTime() - start
94+
95+
// If there is an auto next planned soon or was in the past
96+
if (partInstance.part.expectedDuration - playbackDuration < 0) {
97+
return false
98+
}
99+
}
100+
101+
return true
102+
}
103+
104+
modifyPartForQuickLoop(
105+
partInstance.part,
106+
segmentRanks,
107+
rundownRanks,
108+
playlist,
109+
studio,
110+
quickLoopStartPosition,
111+
quickLoopEndPosition,
112+
canAutoNext // do not adjust the part instance if we have passed the time where we can still enable auto next
113+
)
114+
}
115+
77116
export function findMarkerPosition(
78117
marker: QuickLoopMarker,
79118
fallback: number,

meteor/server/publications/partInstancesUI/publication.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ import { protectString } from '@sofie-automation/corelib/dist/protectedString'
2828
import { Match } from '../../../lib/check'
2929
import { RundownReadAccess } from '../../security/rundown'
3030
import { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartInstance'
31-
import { extractRanks, findMarkerPosition, modifyPartForQuickLoop, stringsToIndexLookup } from '../lib/quickLoop'
31+
import {
32+
extractRanks,
33+
findMarkerPosition,
34+
modifyPartInstanceForQuickLoop,
35+
stringsToIndexLookup,
36+
} from '../lib/quickLoop'
3237

3338
interface UIPartInstancesArgs {
3439
readonly playlistActivationId: RundownPlaylistActivationId
@@ -183,8 +188,8 @@ export async function manipulateUIPartInstancesPublicationData(
183188
invalidatedSegmentsSet.has(partInstance.segmentId) ||
184189
invalidatedPartInstancesSet.has(partInstance._id)
185190
) {
186-
modifyPartForQuickLoop(
187-
partInstance.part,
191+
modifyPartInstanceForQuickLoop(
192+
partInstance,
188193
segmentRanks,
189194
rundownRanks,
190195
playlist,

packages/job-worker/src/playout/model/services/QuickLoopService.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { PlayoutPartInstanceModel } from '../PlayoutPartInstanceModel'
1414
import { JobContext } from '../../../jobs'
1515
import { clone } from '@sofie-automation/corelib/dist/lib'
1616
import { DEFAULT_FALLBACK_PART_DURATION } from '@sofie-automation/shared-lib/dist/core/constants'
17+
import { getCurrentTime } from '../../../lib'
1718

1819
export class QuickLoopService {
1920
constructor(private readonly context: JobContext, private readonly playoutModel: PlayoutModelReadonly) {}
@@ -54,7 +55,23 @@ export class QuickLoopService {
5455
expectedDurationWithTransition = fallbackPartDuration
5556
}
5657
}
57-
autoNext = autoNext || (isLoopingOverriden && (expectedDuration ?? 0) > 0)
58+
59+
const tooCloseToAutonext = () => {
60+
const start = partInstanceModel.partInstance.timings?.plannedStartedPlayback
61+
if (start !== undefined && partInstanceModel.partInstance.part.expectedDuration) {
62+
// date.now - start = playback duration, duration + offset gives position in part
63+
const playbackDuration = getCurrentTime() - start
64+
65+
// If there is an auto next planned
66+
if (partInstanceModel.partInstance.part.expectedDuration - playbackDuration < 0) {
67+
return true
68+
}
69+
}
70+
71+
return false
72+
}
73+
74+
autoNext = autoNext || (isLoopingOverriden && (expectedDuration ?? 0) > 0 && !tooCloseToAutonext())
5875
return { autoNext, expectedDuration, expectedDurationWithTransition }
5976
}
6077

packages/job-worker/src/playout/timeline/rundown.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,18 @@ export function buildTimelineObjsForRundown(
147147
currentPartEnable.duration =
148148
partInstancesInfo.current.partInstance.part.expectedDuration +
149149
partInstancesInfo.current.calculatedTimings.toPartDelay
150+
151+
if (
152+
typeof currentPartEnable.start === 'number' &&
153+
currentPartEnable.start + currentPartEnable.duration < getCurrentTime()
154+
) {
155+
logger.warn('Prevented setting the end of an autonext in the past')
156+
// note - this will cause a small glitch on air where the next part is skipped into because this calculation does not account
157+
// for the time it takes between timeline generation and timeline execution. That small glitch is preferable to setting the time
158+
// very far in the past however. To do this properly we should support setting the "end" to "now" and have that calculated after
159+
// timeline generation as we do for start times.
160+
currentPartEnable.duration = getCurrentTime() - currentPartEnable.start
161+
}
150162
}
151163
const currentPartGroup = createPartGroup(partInstancesInfo.current.partInstance, currentPartEnable)
152164

0 commit comments

Comments
 (0)