Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
id: 'H5CBGYjThrMSmaYvRaa5FVKJIzk_'
name: 'Intro'
autoNext: false
createdByAdLib: false
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ $defs:
name:
description: User-presentable name of the part
type: string
createdByAdLib:
description: Whether this part was created by an adlib
type: boolean
default: false
autoNext:
description: If this part will progress to the next automatically
type: boolean
default: false
required: [id, name]
required: [id, name, createdByAdLib]
examples:
- $ref: './partBase-example.yaml'
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ $defs:
state:
description: Set only for the current or next part
$ref: '#/$defs/resolvedPartState'
createdByAdLib:
type: boolean
description: Whether this part was created by an adlib
publicData:
description: Optional arbitrary data
timing:
Expand All @@ -51,6 +48,6 @@ $defs:
type: array
items:
$ref: '../../piece/resolvedPiece/resolvedPiece.yaml#/$defs/resolvedPiece'
required: [instanceId, externalId, rank, createdByAdLib, timing, pieces, invalid, floated, untimed]
required: [instanceId, externalId, rank, timing, pieces, invalid, floated, untimed]
examples:
- $ref: './resolvedPart-example.yaml'
13 changes: 9 additions & 4 deletions packages/live-status-gateway-api/src/generated/asyncapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -381,17 +381,23 @@ channels:
name:
description: User-presentable name of the part
type: string
createdByAdLib:
description: Whether this part was created by an adlib
type: boolean
default: false
autoNext:
description: If this part will progress to the next automatically
type: boolean
default: false
required:
- id
- name
- createdByAdLib
examples:
- id: H5CBGYjThrMSmaYvRaa5FVKJIzk_
name: Intro
autoNext: false
createdByAdLib: false
- type: object
title: PartStatus
properties:
Expand Down Expand Up @@ -485,6 +491,7 @@ channels:
id: H5CBGYjThrMSmaYvRaa5FVKJIzk_
name: Intro
autoNext: false
createdByAdLib: false
- type: object
title: CurrentPartStatus
properties:
Expand Down Expand Up @@ -532,6 +539,7 @@ channels:
id: H5CBGYjThrMSmaYvRaa5FVKJIzk_
name: Intro
autoNext: false
createdByAdLib: false
- type: "null"
currentSegment:
oneOf:
Expand Down Expand Up @@ -625,6 +633,7 @@ channels:
id: H5CBGYjThrMSmaYvRaa5FVKJIzk_
name: Intro
autoNext: false
createdByAdLib: false
required:
- timing
- parts
Expand Down Expand Up @@ -1350,9 +1359,6 @@ channels:
enum:
- current
- next
createdByAdLib:
type: boolean
description: Whether this part was created by an adlib
publicData:
description: Optional arbitrary data
timing:
Expand Down Expand Up @@ -1499,7 +1505,6 @@ channels:
- instanceId
- externalId
- rank
- createdByAdLib
- timing
- pieces
- invalid
Expand Down
20 changes: 16 additions & 4 deletions packages/live-status-gateway-api/src/generated/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ interface CurrentPartStatus {
* User-presentable name of the part
*/
name: string
/**
* Whether this part was created by an adlib
*/
createdByAdLib: boolean
/**
* If this part will progress to the next automatically
*/
Expand Down Expand Up @@ -348,6 +352,10 @@ interface CurrentSegmentPart {
* User-presentable name of the part
*/
name: string
/**
* Whether this part was created by an adlib
*/
createdByAdLib: boolean
/**
* If this part will progress to the next automatically
*/
Expand All @@ -373,6 +381,10 @@ interface PartStatus {
* User-presentable name of the part
*/
name: string
/**
* Whether this part was created by an adlib
*/
createdByAdLib: boolean
/**
* If this part will progress to the next automatically
*/
Expand Down Expand Up @@ -857,6 +869,10 @@ interface ResolvedPart {
* User-presentable name of the part
*/
name: string
/**
* Whether this part was created by an adlib
*/
createdByAdLib: boolean
/**
* If this part will progress to the next automatically
*/
Expand Down Expand Up @@ -893,10 +909,6 @@ interface ResolvedPart {
* Set only for the current or next part
*/
state?: ResolvedPartState
/**
* Whether this part was created by an adlib
*/
createdByAdLib: boolean
/**
* Optional arbitrary data
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ describe('ActivePlaylistTopic', () => {
id: 'PART_1',
name: 'Test Part',
segmentId: 'SEGMENT_1',
createdByAdLib: false,
timing: { startTime: 1600000060000, expectedDurationMs: 10000, projectedEndTime: 1600000070000 },
pieces: [],
autoNext: undefined,
Expand All @@ -158,6 +159,7 @@ describe('ActivePlaylistTopic', () => {
{
id: 'PART_1',
name: 'Test Part',
createdByAdLib: false,
timing: {
expectedDurationMs: 10000,
},
Expand All @@ -181,6 +183,85 @@ describe('ActivePlaylistTopic', () => {
)
})

it('marks adlib-created parts in active playlist status', async () => {
const handlers = makeMockHandlers()
const topic = new ActivePlaylistTopic(makeMockLogger(), handlers)
const mockSubscriber = makeMockSubscriber()

const currentPartInstanceId = 'CURRENT_PART_INSTANCE_ID'
const nextPartInstanceId = 'NEXT_PART_INSTANCE_ID'

const playlist = makeTestPlaylist()
playlist.activationId = protectString('somethingRandom')
playlist.currentPartInfo = {
consumesQueuedSegmentId: false,
manuallySelected: false,
partInstanceId: protectString(currentPartInstanceId),
rundownId: playlist.rundownIdsInOrder[0],
}
playlist.nextPartInfo = {
consumesQueuedSegmentId: false,
manuallySelected: false,
partInstanceId: protectString(nextPartInstanceId),
rundownId: playlist.rundownIdsInOrder[0],
}
handlers.playlistHandler.notify(playlist)

const testShowStyleBase = makeTestShowStyleBase()
handlers.showStyleBaseHandler.notify(testShowStyleBase as ShowStyleBaseExt)

const segment1id = protectString('SEGMENT_1')
const currentPart: Partial<DBPart> = {
_id: protectString('PART_1'),
title: 'Current AdLib Part',
segmentId: segment1id,
expectedDurationWithTransition: 10000,
expectedDuration: 10000,
}
const nextPart: Partial<DBPart> = {
_id: protectString('PART_2'),
title: 'Next AdLib Part',
segmentId: segment1id,
expectedDurationWithTransition: 8000,
expectedDuration: 8000,
}
const testPartInstances: PartialDeep<SelectedPartInstances> = {
current: {
_id: currentPartInstanceId,
part: currentPart,
segmentId: segment1id,
orphaned: 'adlib-part',
},
next: {
_id: nextPartInstanceId,
part: nextPart,
segmentId: segment1id,
orphaned: 'adlib-part',
},
firstInSegmentPlayout: {},
inCurrentSegment: [
literal<PartialDeep<DBPartInstance>>({
_id: protectString(currentPartInstanceId),
part: currentPart,
segmentId: segment1id,
orphaned: 'adlib-part',
}),
] as DBPartInstance[],
}
handlers.partInstancesHandler.notify(testPartInstances as SelectedPartInstances)
handlers.partsHandler.notify([currentPart as DBPart, nextPart as DBPart])
handlers.segmentHandler.notify({
_id: segment1id,
} as DBSegment)

topic.addSubscriber(mockSubscriber)

const sentStatus = JSON.parse(mockSubscriber.send.mock.calls[0][0] as string) as ActivePlaylistEvent
expect(sentStatus.currentPart?.createdByAdLib).toBe(true)
expect(sentStatus.nextPart?.createdByAdLib).toBe(true)
expect(sentStatus.currentSegment?.parts[0].createdByAdLib).toBe(true)
})

it('provides segment and part with segment timing', async () => {
const handlers = makeMockHandlers()
const topic = new ActivePlaylistTopic(makeMockLogger(), handlers)
Expand Down Expand Up @@ -247,6 +328,7 @@ describe('ActivePlaylistTopic', () => {
id: 'PART_1',
name: 'Test Part',
segmentId: 'SEGMENT_1',
createdByAdLib: false,
timing: { startTime: 1600000060000, expectedDurationMs: 10000, projectedEndTime: 1600000070000 },
pieces: [],
autoNext: undefined,
Expand All @@ -265,6 +347,7 @@ describe('ActivePlaylistTopic', () => {
{
id: 'PART_1',
name: 'Test Part',
createdByAdLib: false,
timing: {
expectedDurationMs: 10000,
},
Expand Down
29 changes: 16 additions & 13 deletions packages/live-status-gateway/src/topics/activePlaylistTopic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export class ActivePlaylistTopic extends WebSocketTopicBase implements WebSocket
id: unprotectString(currentPart._id),
name: currentPart.title,
autoNext: currentPart.autoNext,
createdByAdLib: this._currentPartInstance.orphaned === 'adlib-part',
segmentId: unprotectString(currentPart.segmentId),
timing: calculateCurrentPartTiming(
this._currentPartInstance,
Expand Down Expand Up @@ -156,19 +157,21 @@ export class ActivePlaylistTopic extends WebSocketTopicBase implements WebSocket
),
})
: null,
nextPart: nextPart
? literal<PartStatus>({
id: unprotectString(nextPart._id),
name: nextPart.title,
autoNext: nextPart.autoNext,
segmentId: unprotectString(nextPart.segmentId),
pieces:
this._pieceInstancesInNextPartInstance?.map((piece) =>
toPieceStatus(piece, this._showStyleBaseExt)
) ?? [],
publicData: nextPart.publicData,
})
: null,
nextPart:
this._nextPartInstance && nextPart
? literal<PartStatus>({
id: unprotectString(nextPart._id),
name: nextPart.title,
autoNext: nextPart.autoNext,
createdByAdLib: this._nextPartInstance.orphaned === 'adlib-part',
segmentId: unprotectString(nextPart.segmentId),
pieces:
this._pieceInstancesInNextPartInstance?.map((piece) =>
toPieceStatus(piece, this._showStyleBaseExt)
) ?? [],
publicData: nextPart.publicData,
})
: null,
quickLoop: this.transformQuickLoopStatus(),
publicData: this._activePlaylist.publicData,
playoutState: this._activePlaylist.publicPlayoutPersistentState,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { DBPart } from '@sofie-automation/corelib/dist/dataModel/Part'
import { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartInstance'
import { protectString } from '@sofie-automation/corelib/dist/protectedString'
import { getCurrentSegmentParts } from '../segmentParts.js'

function makePart(id: string, title: string): DBPart {
return {
_id: protectString(id),
_rank: 0,
rundownId: protectString('rundown_1'),
segmentId: protectString('segment_1'),
notes: [],
externalId: id,
expectedDuration: 1000,
expectedDurationWithTransition: 1000,
title,
}
}

describe('segmentParts - getCurrentSegmentParts', () => {
it('marks adlib-created parts', () => {
const adlibPart = makePart('part_1', 'AdLib Part')
const normalPart = makePart('part_2', 'Normal Part')

const result = getCurrentSegmentParts(
[
{
_id: protectString('partInstance_1'),
part: adlibPart,
orphaned: 'adlib-part',
} as DBPartInstance,
],
[adlibPart, normalPart]
)

expect(result).toEqual([
{
id: 'part_1',
name: 'AdLib Part',
autoNext: undefined,
createdByAdLib: true,
timing: { expectedDurationMs: 1000 },
},
{
id: 'part_2',
name: 'Normal Part',
autoNext: undefined,
createdByAdLib: false,
timing: { expectedDurationMs: 1000 },
},
])
})
})
Loading
Loading