1- import type { IMOSDevice } from '@mos-connection/connector'
1+ import { getMosTypes , IMOSObjectStatus , type IMOSDevice } from '@mos-connection/connector'
22import type { MosDeviceStatusesConfig } from './generated/devices'
33import type { CoreMosDeviceHandler } from './CoreMosDeviceHandler'
44import {
@@ -8,15 +8,22 @@ import {
88 stringifyError ,
99 SubscriptionId ,
1010} from '@sofie-automation/server-core-integration'
11- import type { IngestRundownStatus } from '@sofie-automation/shared-lib/dist/ingest/rundownStatus'
12- import { RundownId } from '@sofie-automation/shared-lib/dist/core/model/Ids'
11+ import type { IngestPartStatus , IngestRundownStatus } from '@sofie-automation/shared-lib/dist/ingest/rundownStatus'
12+ import type { RundownId } from '@sofie-automation/shared-lib/dist/core/model/Ids'
1313import type winston = require( 'winston' )
14+ import { Queue } from '@sofie-automation/server-core-integration/dist/lib/queue'
15+
16+ const MOS_STATUS_UNKNOWN = '' as IMOSObjectStatus // nocommit - check this
17+
18+ const mosTypes = getMosTypes ( false )
1419
1520export class MosStatusHandler {
1621 readonly #logger: winston . Logger
1722 readonly #mosDevice: IMOSDevice
1823 readonly #coreMosHandler: CoreMosDeviceHandler
1924
25+ readonly #messageQueue = new Queue ( )
26+
2027 #subId: SubscriptionId | undefined
2128 #observer: Observer < IngestRundownStatus > | undefined
2229
@@ -72,7 +79,28 @@ export class MosStatusHandler {
7279 const statusDiff = diffStatuses ( previousStatuses , newStatuses )
7380 if ( statusDiff . length === 0 ) return
7481
75- // nocommit - send statuses to MOS device. with a queue?
82+ const diffTime = mosTypes . mosTime . create ( Date . now ( ) )
83+
84+ // nocommit - should this be done with some concurrency?
85+ for ( const status of statusDiff ) {
86+ this . #messageQueue
87+ . putOnQueue ( async ( ) => {
88+ // Send status
89+ await this . #mosDevice. sendStoryStatus ( {
90+ RunningOrderId : mosTypes . mosString128 . create ( status . rundownExternalId ) ,
91+ ID : mosTypes . mosString128 . create ( status . storyId ) ,
92+ Status : status . mosStatus ,
93+ Time : diffTime ,
94+ } )
95+ } )
96+ . catch ( ( e ) => {
97+ this . #logger. error (
98+ `Error sending of "${ status . rundownExternalId } "-"${
99+ status . storyId
100+ } " status to MOS device: ${ stringifyError ( e ) } `
101+ )
102+ } )
103+ }
76104
77105 throw new Error ( 'Method not implemented.' )
78106 }
@@ -86,16 +114,81 @@ export class MosStatusHandler {
86114}
87115
88116interface StoryStatusItem {
117+ rundownExternalId : string
89118 storyId : string
90- mosStatus : string
119+ mosStatus : IMOSObjectStatus
91120}
92121
93122function diffStatuses (
94123 previousStatuses : IngestRundownStatus | undefined ,
95124 newStatuses : IngestRundownStatus | undefined
96125) : StoryStatusItem [ ] {
97- if ( ! previousStatuses && ! newStatuses ) return [ ]
126+ const rundownExternalId = previousStatuses ?. externalId ?? newStatuses ?. externalId
127+
128+ if ( ( ! previousStatuses && ! newStatuses ) || ! rundownExternalId ) return [ ]
129+
130+ const statuses : StoryStatusItem [ ] = [ ]
131+
132+ const previousStories = buildStoriesMap ( previousStatuses )
133+ const newStories = buildStoriesMap ( newStatuses )
98134
99- // TODO
100- return [ ]
135+ // Process any removed stories first
136+ for ( const storyId of previousStories . keys ( ) ) {
137+ if ( ! newStories . has ( storyId ) ) {
138+ // The story has been removed
139+ statuses . push ( {
140+ rundownExternalId,
141+ storyId,
142+ mosStatus : MOS_STATUS_UNKNOWN ,
143+ } )
144+ }
145+ }
146+
147+ // Then any remaining stories in order
148+ for ( const [ storyId , status ] of newStories ) {
149+ const previousStatus = previousStories . get ( storyId )
150+
151+ const newMosStatus = buildMosStatus ( status )
152+ if ( ! previousStatus || buildMosStatus ( previousStatus ) !== newMosStatus ) {
153+ statuses . push ( {
154+ rundownExternalId,
155+ storyId,
156+ mosStatus : newMosStatus ,
157+ } )
158+ }
159+ }
160+
161+ return statuses
162+ }
163+
164+ function buildStoriesMap ( state : IngestRundownStatus | undefined ) : Map < string , IngestPartStatus > {
165+ const stories = new Map < string , IngestPartStatus > ( )
166+
167+ if ( state ) {
168+ for ( const segment of state . segments ) {
169+ for ( const part of segment . parts ) {
170+ stories . set ( part . externalId , part )
171+ }
172+ }
173+ }
174+
175+ return stories
176+ }
177+
178+ function buildMosStatus ( story : IngestPartStatus ) : IMOSObjectStatus {
179+ switch ( story . playbackStatus ) {
180+ case 'playing' :
181+ return IMOSObjectStatus . PLAY
182+ case 'stopped' :
183+ return IMOSObjectStatus . STOP
184+ default :
185+ switch ( story . isReady ) {
186+ case true :
187+ return IMOSObjectStatus . READY
188+ case false :
189+ return IMOSObjectStatus . NOT_READY
190+ default :
191+ return MOS_STATUS_UNKNOWN
192+ }
193+ }
101194}
0 commit comments