Skip to content

Commit 988274d

Browse files
authored
Merge pull request #1352 from nrkno/fix/sofie-3661/broken-hold
2 parents d2a3cdf + a7d6999 commit 988274d

File tree

4 files changed

+53
-47
lines changed

4 files changed

+53
-47
lines changed

packages/job-worker/src/playout/model/PlayoutModel.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ export interface PlayoutModel extends PlayoutModelReadonly, StudioPlayoutModelBa
234234
*/
235235
cycleSelectedPartInstances(): void
236236

237+
/**
238+
* Reset the hold state to a base state
239+
*/
240+
resetHoldState(): void
241+
237242
/**
238243
* Set the RundownPlaylist as deactivated
239244
*/

packages/job-worker/src/playout/model/implementation/PlayoutModelImpl.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -420,15 +420,13 @@ export class PlayoutModelImpl extends PlayoutModelReadonlyImpl implements Playou
420420
this.playlistImpl.nextPartInfo = null
421421
this.playlistImpl.lastTakeTime = getCurrentTime()
422422

423-
if (!this.playlistImpl.holdState || this.playlistImpl.holdState === RundownHoldState.COMPLETE) {
424-
this.playlistImpl.holdState = RundownHoldState.NONE
425-
} else {
426-
this.playlistImpl.holdState = this.playlistImpl.holdState + 1
427-
}
428-
429423
this.#playlistHasChanged = true
430424
}
431425

426+
resetHoldState(): void {
427+
this.setHoldState(RundownHoldState.NONE)
428+
}
429+
432430
deactivatePlaylist(): void {
433431
delete this.playlistImpl.activationId
434432

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

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -178,20 +178,23 @@ export async function performTakeToNextedPart(
178178
}
179179
}
180180

181+
// If hold is COMPLETE, clear the hold state by this take
181182
if (playoutModel.playlist.holdState === RundownHoldState.COMPLETE) {
182183
playoutModel.setHoldState(RundownHoldState.NONE)
183184

184-
// If hold is active, then this take is to clear it
185+
// If hold is ACTIVE, then this take is to complete it
185186
} else if (playoutModel.playlist.holdState === RundownHoldState.ACTIVE) {
186187
await completeHold(context, playoutModel, await pShowStyle, currentPartInstance)
187188

189+
await updateTimeline(context, playoutModel)
190+
188191
if (span) span.end()
189192

190193
return
191194
}
192195

193196
const takePartInstance = nextPartInstance
194-
if (!takePartInstance) throw new Error('takePart not found!')
197+
if (!takePartInstance) throw new Error('takePartInstance not found!')
195198
const takeRundown = playoutModel.getRundown(takePartInstance.partInstance.rundownId)
196199
if (!takeRundown)
197200
throw new Error(`takeRundown: takeRundown not found! ("${takePartInstance.partInstance.rundownId}")`)
@@ -263,12 +266,10 @@ export async function performTakeToNextedPart(
263266
// Once everything is synced, we can choose the next part
264267
await setNextPart(context, playoutModel, nextPart, false)
265268

266-
// Setup the parts for the HOLD we are starting
267-
if (
268-
playoutModel.playlist.previousPartInfo &&
269-
(playoutModel.playlist.holdState as RundownHoldState) === RundownHoldState.ACTIVE
270-
) {
271-
startHold(context, currentPartInstance, nextPartInstance)
269+
// If the Hold is PENDING, make it active
270+
if (playoutModel.playlist.holdState === RundownHoldState.PENDING) {
271+
// Setup the parts for the HOLD we are starting
272+
activateHold(context, playoutModel, currentPartInstance, takePartInstance)
272273
}
273274
await afterTake(context, playoutModel, takePartInstance)
274275

@@ -535,35 +536,39 @@ export async function afterTake(
535536
/**
536537
* A Hold starts by extending the "extendOnHold"-able pieces in the previous Part.
537538
*/
538-
function startHold(
539+
function activateHold(
539540
context: JobContext,
541+
playoutModel: PlayoutModel,
540542
holdFromPartInstance: PlayoutPartInstanceModel | null,
541543
holdToPartInstance: PlayoutPartInstanceModel | undefined
542544
) {
543545
if (!holdFromPartInstance) throw new Error('previousPart not found!')
544546
if (!holdToPartInstance) throw new Error('currentPart not found!')
545-
const span = context.startSpan('startHold')
547+
const span = context.startSpan('activateHold')
548+
549+
playoutModel.setHoldState(RundownHoldState.ACTIVE)
546550

547551
// Make a copy of any item which is flagged as an 'infinite' extension
548552
const pieceInstancesToCopy = holdFromPartInstance.pieceInstances.filter((p) => !!p.pieceInstance.piece.extendOnHold)
549-
pieceInstancesToCopy.forEach((instance) => {
550-
if (!instance.pieceInstance.infinite) {
551-
// mark current one as infinite
552-
instance.prepareForHold()
553-
554-
// This gets deleted once the nextpart is activated, so it doesnt linger for long
555-
const extendedPieceInstance = holdToPartInstance.insertHoldPieceInstance(instance)
556-
557-
const content = clone(instance.pieceInstance.piece.content) as VTContent | undefined
558-
if (content?.fileName && content.sourceDuration && instance.pieceInstance.plannedStartedPlayback) {
559-
content.seek = Math.min(
560-
content.sourceDuration,
561-
getCurrentTime() - instance.pieceInstance.plannedStartedPlayback
562-
)
563-
}
564-
extendedPieceInstance.updatePieceProps({ content })
553+
for (const instance of pieceInstancesToCopy) {
554+
// skip any infinites
555+
if (instance.pieceInstance.infinite) continue
556+
557+
instance.prepareForHold()
558+
559+
// This gets deleted once the nextpart is activated, so it doesnt linger for long
560+
const extendedPieceInstance = holdToPartInstance.insertHoldPieceInstance(instance)
561+
562+
const content = clone(instance.pieceInstance.piece.content) as VTContent | undefined
563+
if (content?.fileName && content.sourceDuration && instance.pieceInstance.plannedStartedPlayback) {
564+
content.seek = Math.min(
565+
content.sourceDuration,
566+
getCurrentTime() - instance.pieceInstance.plannedStartedPlayback
567+
)
565568
}
566-
})
569+
extendedPieceInstance.updatePieceProps({ content })
570+
}
571+
567572
if (span) span.end()
568573
}
569574

@@ -575,19 +580,16 @@ async function completeHold(
575580
): Promise<void> {
576581
playoutModel.setHoldState(RundownHoldState.COMPLETE)
577582

578-
if (playoutModel.playlist.currentPartInfo) {
579-
if (!currentPartInstance) throw new Error('currentPart not found!')
583+
if (!playoutModel.playlist.currentPartInfo) return
584+
if (!currentPartInstance) throw new Error('currentPart not found!')
580585

581-
// Clear the current extension line
582-
innerStopPieces(
583-
context,
584-
playoutModel,
585-
showStyleCompound.sourceLayers,
586-
currentPartInstance,
587-
(p) => !!p.infinite?.fromHold,
588-
undefined
589-
)
590-
}
591-
592-
await updateTimeline(context, playoutModel)
586+
// Clear the current extension line
587+
innerStopPieces(
588+
context,
589+
playoutModel,
590+
showStyleCompound.sourceLayers,
591+
currentPartInstance,
592+
(p) => !!p.infinite?.fromHold,
593+
undefined
594+
)
593595
}

packages/job-worker/src/playout/timings/partPlayback.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export async function onPartPlaybackStarted(
5858
// this is the next part, clearly an autoNext has taken place
5959

6060
playoutModel.cycleSelectedPartInstances()
61+
playoutModel.resetHoldState()
6162

6263
reportPartInstanceHasStarted(context, playoutModel, playingPartInstance, data.startedPlayback)
6364

0 commit comments

Comments
 (0)