Skip to content

Commit 7af2a8a

Browse files
committed
wip: remove old flow and add some todos to new flow
1 parent 83ac74f commit 7af2a8a

File tree

10 files changed

+31
-202
lines changed

10 files changed

+31
-202
lines changed

packages/corelib/src/dataModel/Rundown.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ export interface Rundown {
5757
*/
5858
orphaned?: RundownOrphanedReason
5959

60-
/** Last sent storyStatus to ingestDevice (MOS) */
61-
notifiedCurrentPlayingPartExternalId?: string
62-
6360
/** Holds notes (warnings / errors) thrown by the blueprints during creation */
6461
notes?: Array<RundownNote>
6562

packages/corelib/src/worker/events.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { PartInstanceId, RundownId, RundownPlaylistId, StudioId } from '../dataM
33
export enum EventsJobs {
44
PartInstanceTimings = 'partInstanceTimings',
55
RundownDataChanged = 'rundownDataChanged',
6-
NotifyCurrentlyPlayingPart = 'notifyCurrentlyPlayingPart',
76
}
87

98
export interface PartInstanceTimingsProps {
@@ -16,20 +15,13 @@ export interface RundownDataChangedProps {
1615
rundownId: RundownId
1716
}
1817

19-
export interface NotifyCurrentlyPlayingPartProps {
20-
rundownId: RundownId
21-
isRehearsal: boolean
22-
partExternalId: string | null
23-
}
24-
2518
/**
2619
* Set of valid functions, of form:
2720
* `id: (data) => return`
2821
*/
2922
export type EventsJobFunc = {
3023
[EventsJobs.PartInstanceTimings]: (data: PartInstanceTimingsProps) => void
3124
[EventsJobs.RundownDataChanged]: (data: RundownDataChangedProps) => void
32-
[EventsJobs.NotifyCurrentlyPlayingPart]: (data: NotifyCurrentlyPlayingPartProps) => void
3325
}
3426

3527
export function getEventsQueueName(id: StudioId): string {

packages/job-worker/src/events/handle.ts

Lines changed: 2 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
NotifyCurrentlyPlayingPartProps,
3-
PartInstanceTimingsProps,
4-
RundownDataChangedProps,
5-
} from '@sofie-automation/corelib/dist/worker/events'
1+
import { PartInstanceTimingsProps, RundownDataChangedProps } from '@sofie-automation/corelib/dist/worker/events'
62
import { getCurrentTime } from '../lib'
73
import { JobContext } from '../jobs'
84
import { logger } from '../logging'
@@ -17,16 +13,7 @@ import { stringifyError } from '@sofie-automation/shared-lib/dist/lib/stringifyE
1713
import { ExternalMessageQueueObj } from '@sofie-automation/corelib/dist/dataModel/ExternalMessageQueue'
1814
import { ICollection, MongoModifier } from '../db'
1915
import { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist'
20-
import { ExternalMessageQueueObjId, PeripheralDeviceId } from '@sofie-automation/corelib/dist/dataModel/Ids'
21-
import { runWithRundownLock } from '../ingest/lock'
22-
import {
23-
PeripheralDevice,
24-
PeripheralDeviceCategory,
25-
PeripheralDeviceType,
26-
} from '@sofie-automation/corelib/dist/dataModel/PeripheralDevice'
27-
import { MOS } from '@sofie-automation/corelib'
28-
import { executePeripheralDeviceFunction } from '../peripheralDevice'
29-
import { DEFAULT_MOS_TIMEOUT_TIME } from '@sofie-automation/shared-lib/dist/core/constants'
16+
import { ExternalMessageQueueObjId } from '@sofie-automation/corelib/dist/dataModel/Ids'
3017

3118
async function getBlueprintAndDependencies(context: JobContext, rundown: ReadonlyDeep<DBRundown>) {
3219
const pShowStyle = context.getShowStyleCompound(rundown.showStyleVariantId, rundown.showStyleBaseId)
@@ -226,121 +213,3 @@ export async function handleRundownDataHasChanged(context: JobContext, data: Run
226213
logger.error(`Error in showStyleBlueprint.onRundownDataChangedEvent: ${stringifyError(err)}`)
227214
}
228215
}
229-
230-
export async function handleNotifyCurrentlyPlayingPart(
231-
context: JobContext,
232-
data: NotifyCurrentlyPlayingPartProps
233-
): Promise<void> {
234-
const rundown = await context.directCollections.Rundowns.findOne(data.rundownId)
235-
if (!rundown) {
236-
logger.warn(`Rundown "${data.rundownId} is missing. Skipping notifyCurrentPlayingPart`)
237-
return
238-
}
239-
240-
if (rundown.source.type !== 'nrcs') {
241-
logger.warn(`Rundown "${rundown._id} has no peripheralDevice. Skipping notifyCurrentPlayingPart`)
242-
return
243-
}
244-
245-
const device = await context.directCollections.PeripheralDevices.findOne({
246-
_id: rundown.source.peripheralDeviceId,
247-
// Future: we really should be constraining this to the studio, but that is often only defined on the parent of this device
248-
// studioId: context.studioId,
249-
parentDeviceId: { $exists: true },
250-
})
251-
if (!device || !device.parentDeviceId) {
252-
logger.warn(
253-
`PeripheralDevice "${rundown.source.peripheralDeviceId}" for Rundown "${rundown._id} not found. Skipping notifyCurrentPlayingPart`
254-
)
255-
return
256-
}
257-
const parentDevice = await context.directCollections.PeripheralDevices.findOne({
258-
_id: device.parentDeviceId,
259-
studioId: context.studioId,
260-
parentDeviceId: { $exists: false },
261-
})
262-
if (!parentDevice) {
263-
logger.warn(
264-
`PeripheralDevice "${rundown.source.peripheralDeviceId}" for Rundown "${rundown._id} not found. Skipping notifyCurrentPlayingPart`
265-
)
266-
return
267-
}
268-
269-
const previousPlayingPartExternalId: string | null = rundown.notifiedCurrentPlayingPartExternalId || null
270-
const currentPlayingPartExternalId: string | null = data.isRehearsal ? null : data.partExternalId
271-
272-
// Lock the rundown so that we are allowed to write to it
273-
// This is technically a bit of a race condition, but is really low risk and low impact if it does
274-
await runWithRundownLock(context, rundown._id, async (rundown0) => {
275-
if (!rundown0) return
276-
277-
await context.directCollections.Rundowns.update(
278-
rundown._id,
279-
currentPlayingPartExternalId
280-
? {
281-
$set: {
282-
notifiedCurrentPlayingPartExternalId: currentPlayingPartExternalId,
283-
},
284-
}
285-
: {
286-
$unset: {
287-
notifiedCurrentPlayingPartExternalId: 1,
288-
},
289-
}
290-
)
291-
})
292-
293-
// TODO: refactor this to be non-mos centric
294-
if (device.category === PeripheralDeviceCategory.INGEST && device.type === PeripheralDeviceType.MOS) {
295-
// Note: rundown may not be up to date anymore
296-
await notifyCurrentPlayingPartMOS(
297-
context,
298-
device,
299-
rundown.externalId,
300-
previousPlayingPartExternalId,
301-
currentPlayingPartExternalId
302-
)
303-
}
304-
}
305-
306-
async function notifyCurrentPlayingPartMOS(
307-
context: JobContext,
308-
peripheralDevice: PeripheralDevice,
309-
rundownExternalId: string,
310-
oldPlayingPartExternalId: string | null,
311-
newPlayingPartExternalId: string | null
312-
): Promise<void> {
313-
if (oldPlayingPartExternalId !== newPlayingPartExternalId) {
314-
// New implementation 2022 only sends PLAY, never stop, after getting advice from AP
315-
// Reason 1: NRK ENPS "sendt tid" (elapsed time) stopped working in ENPS 8/9 when doing STOP prior to PLAY
316-
// Reason 2: there's a delay between the STOP (yellow line disappears) and PLAY (yellow line re-appears), which annoys the users
317-
if (newPlayingPartExternalId) {
318-
try {
319-
await setStoryStatusMOS(
320-
context,
321-
peripheralDevice._id,
322-
rundownExternalId,
323-
newPlayingPartExternalId,
324-
MOS.IMOSObjectStatus.PLAY
325-
)
326-
} catch (error) {
327-
logger.error(`Error in setStoryStatus PLAY: ${stringifyError(error)}`)
328-
}
329-
}
330-
}
331-
}
332-
333-
async function setStoryStatusMOS(
334-
context: JobContext,
335-
deviceId: PeripheralDeviceId,
336-
rundownExternalId: string,
337-
storyId: string,
338-
status: MOS.IMOSObjectStatus
339-
): Promise<void> {
340-
logger.debug('setStoryStatus', { deviceId, externalId: rundownExternalId, storyId, status })
341-
return executePeripheralDeviceFunction(context, deviceId, DEFAULT_MOS_TIMEOUT_TIME + 1000, 'setStoryStatus', [
342-
rundownExternalId,
343-
storyId,
344-
status,
345-
])
346-
}

packages/job-worker/src/ingest/model/implementation/IngestModelImpl.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,6 @@ export class IngestModelImpl implements IngestModel, DatabasePersistedModel {
462462
// owned by elsewhere
463463
airStatus: this.#rundownImpl?.airStatus,
464464
status: this.#rundownImpl?.status,
465-
notifiedCurrentPlayingPartExternalId: this.#rundownImpl?.notifiedCurrentPlayingPartExternalId,
466465
})
467466
deleteAllUndefinedProperties(newRundown)
468467

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@ export async function handleRestorePlaylistSnapshot(
173173
rundownId: rd._id,
174174
}
175175
rd.studioId = snapshot.playlist.studioId
176-
rd.notifiedCurrentPlayingPartExternalId = undefined
177176
}
178177

179178
// TODO: This is too naive. Ideally we should unset it if it isnt valid, as anything other than a match is likely to have issues.
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import { JobContext } from '../../jobs'
22
import { EventsJobFunc, EventsJobs } from '@sofie-automation/corelib/dist/worker/events'
3-
import {
4-
handleNotifyCurrentlyPlayingPart,
5-
handlePartInstanceTimings,
6-
handleRundownDataHasChanged,
7-
} from '../../events/handle'
3+
import { handlePartInstanceTimings, handleRundownDataHasChanged } from '../../events/handle'
84

95
type ExecutableFunction<T extends keyof EventsJobFunc> = (
106
context: JobContext,
@@ -18,5 +14,4 @@ export type EventsJobHandlers = {
1814
export const eventJobHandlers: EventsJobHandlers = {
1915
[EventsJobs.PartInstanceTimings]: handlePartInstanceTimings,
2016
[EventsJobs.RundownDataChanged]: handleRundownDataHasChanged,
21-
[EventsJobs.NotifyCurrentlyPlayingPart]: handleNotifyCurrentlyPlayingPart,
2217
}

packages/mos-gateway/src/CoreMosDeviceHandler.ts

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222
IMOSItem,
2323
IMOSROReadyToAir,
2424
IMOSROFullStory,
25-
IMOSObjectStatus,
2625
IMOSROAck,
2726
getMosTypes,
2827
MosTypes,
@@ -339,42 +338,6 @@ export class CoreMosDeviceHandler {
339338
// console.log('GOT REPLY', results)
340339
return this.fixMosData(ro)
341340
}
342-
async setROStatus(roId: string, status: IMOSObjectStatus): Promise<any> {
343-
// console.log('setStoryStatus')
344-
const result = await this._mosDevice.sendRunningOrderStatus({
345-
ID: this.mosTypes.mosString128.create(roId),
346-
Status: status,
347-
Time: this.mosTypes.mosTime.create(new Date()),
348-
})
349-
350-
// console.log('got result', result)
351-
return this.fixMosData(result)
352-
}
353-
async setStoryStatus(roId: string, storyId: string, status: IMOSObjectStatus): Promise<any> {
354-
// console.log('setStoryStatus')
355-
const result = await this._mosDevice.sendStoryStatus({
356-
RunningOrderId: this.mosTypes.mosString128.create(roId),
357-
ID: this.mosTypes.mosString128.create(storyId),
358-
Status: status,
359-
Time: this.mosTypes.mosTime.create(new Date()),
360-
})
361-
362-
// console.log('got result', result)
363-
return this.fixMosData(result)
364-
}
365-
async setItemStatus(roId: string, storyId: string, itemId: string, status: IMOSObjectStatus): Promise<any> {
366-
// console.log('setStoryStatus')
367-
const result = await this._mosDevice.sendItemStatus({
368-
RunningOrderId: this.mosTypes.mosString128.create(roId),
369-
StoryId: this.mosTypes.mosString128.create(storyId),
370-
ID: this.mosTypes.mosString128.create(itemId),
371-
Status: status,
372-
Time: this.mosTypes.mosTime.create(new Date()),
373-
})
374-
375-
// console.log('got result', result)
376-
return this.fixMosData(result)
377-
}
378341
async replaceStoryItem(
379342
roID: string,
380343
storyID: string,

packages/mos-gateway/src/mosHandler.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,8 @@ export class MosHandler {
303303
this._logger,
304304
mosDevice,
305305
coreMosHandler,
306-
deviceEntry.deviceOptions.statuses
306+
deviceEntry.deviceOptions.statuses,
307+
this.strict
307308
)
308309
}
309310

packages/mos-gateway/src/mosStatusHandler.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getMosTypes, IMOSObjectStatus, type IMOSDevice } from '@mos-connection/connector'
1+
import { getMosTypes, IMOSObjectStatus, MosTypes, type IMOSDevice } from '@mos-connection/connector'
22
import type { MosDeviceStatusesConfig } from './generated/devices'
33
import type { CoreMosDeviceHandler } from './CoreMosDeviceHandler'
44
import {
@@ -8,19 +8,22 @@ import {
88
stringifyError,
99
SubscriptionId,
1010
} from '@sofie-automation/server-core-integration'
11-
import type { IngestPartStatus, IngestRundownStatus } from '@sofie-automation/shared-lib/dist/ingest/rundownStatus'
11+
import {
12+
IngestPartPlaybackStatus,
13+
type IngestPartStatus,
14+
type IngestRundownStatus,
15+
} from '@sofie-automation/shared-lib/dist/ingest/rundownStatus'
1216
import type { RundownId } from '@sofie-automation/shared-lib/dist/core/model/Ids'
1317
import type winston = require('winston')
1418
import { Queue } from '@sofie-automation/server-core-integration/dist/lib/queue'
1519

1620
const MOS_STATUS_UNKNOWN = '' as IMOSObjectStatus // nocommit - check this
1721

18-
const mosTypes = getMosTypes(false)
19-
2022
export class MosStatusHandler {
2123
readonly #logger: winston.Logger
2224
readonly #mosDevice: IMOSDevice
2325
readonly #coreMosHandler: CoreMosDeviceHandler
26+
readonly #mosTypes: MosTypes
2427

2528
readonly #messageQueue = new Queue()
2629

@@ -35,13 +38,15 @@ export class MosStatusHandler {
3538
logger: winston.Logger,
3639
mosDevice: IMOSDevice,
3740
coreMosHandler: CoreMosDeviceHandler,
38-
config: MosDeviceStatusesConfig
41+
config: MosDeviceStatusesConfig,
42+
strictMosTypes: boolean
3943
) {
4044
if (!config.enabled) throw new Error('MosStatusHandler is not enabled')
4145

4246
this.#logger = logger
4347
this.#mosDevice = mosDevice
4448
this.#coreMosHandler = coreMosHandler
49+
this.#mosTypes = getMosTypes(strictMosTypes)
4550

4651
coreMosHandler.core
4752
.autoSubscribe(PeripheralDevicePubSub.ingestDeviceRundownStatus, coreMosHandler.core.deviceId, undefined) // nocommit - does this need a token?
@@ -79,16 +84,16 @@ export class MosStatusHandler {
7984
const statusDiff = diffStatuses(previousStatuses, newStatuses)
8085
if (statusDiff.length === 0) return
8186

82-
const diffTime = mosTypes.mosTime.create(Date.now())
87+
const diffTime = this.#mosTypes.mosTime.create(Date.now())
8388

8489
// nocommit - should this be done with some concurrency?
8590
for (const status of statusDiff) {
8691
this.#messageQueue
8792
.putOnQueue(async () => {
8893
// Send status
8994
await this.#mosDevice.sendStoryStatus({
90-
RunningOrderId: mosTypes.mosString128.create(status.rundownExternalId),
91-
ID: mosTypes.mosString128.create(status.storyId),
95+
RunningOrderId: this.#mosTypes.mosString128.create(status.rundownExternalId),
96+
ID: this.#mosTypes.mosString128.create(status.storyId),
9297
Status: status.mosStatus,
9398
Time: diffTime,
9499
})
@@ -127,6 +132,8 @@ function diffStatuses(
127132

128133
if ((!previousStatuses && !newStatuses) || !rundownExternalId) return []
129134

135+
// nocommit - option/always skip for rehearsal
136+
130137
const statuses: StoryStatusItem[] = []
131138

132139
const previousStories = buildStoriesMap(previousStatuses)
@@ -176,10 +183,17 @@ function buildStoriesMap(state: IngestRundownStatus | undefined): Map<string, In
176183
}
177184

178185
function buildMosStatus(story: IngestPartStatus): IMOSObjectStatus {
186+
// nocommit - implement this rule.
187+
// nocommit - implement options to control behaviour of this
188+
// New implementation 2022 only sends PLAY, never stop, after getting advice from AP
189+
// Reason 1: NRK ENPS "sendt tid" (elapsed time) stopped working in ENPS 8/9 when doing STOP prior to PLAY
190+
// Reason 2: there's a delay between the STOP (yellow line disappears) and PLAY (yellow line re-appears), which annoys the users
191+
// nocommit TLDR: nrk only wants to send PLAY messages
192+
179193
switch (story.playbackStatus) {
180-
case 'playing':
194+
case IngestPartPlaybackStatus.PLAY:
181195
return IMOSObjectStatus.PLAY
182-
case 'stopped':
196+
case IngestPartPlaybackStatus.STOP:
183197
return IMOSObjectStatus.STOP
184198
default:
185199
switch (story.isReady) {

packages/shared-lib/src/ingest/rundownStatus.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ export interface IngestPartStatus {
2929

3030
export enum IngestPartPlaybackStatus {
3131
UNKNOWN = 'unknown',
32-
PLAYING = 'playing',
33-
STOPPED = 'stopped',
32+
PLAY = 'play',
33+
STOP = 'stop',
3434
}

0 commit comments

Comments
 (0)