About Me
This RFC is posted on behalf of the BBC.
Use Case
As an extension of shared control it would be good to have a blueprint method that can respond to changes in the playout devices.
This method should be able to modify current and upcoming parts (potentially the whole running order?)
A sub-task of this would be to able to implement this feedback mechanism in response to HTTP response Body's in the HTTPSend and HTTPListen device.
Proposal
Note: My knowledge of shared control is limited, I believe it operates entirely inside TSR so isn’t something that sofie-core can directly build upon.
Producing events in TSR
I believe there are a few types of events that we will care about:
- When a shared control address is controlled elsewhere (including every time this state changes)
- When a shared control address returns control to sofie
- HTTPSend/Websocket message response received on certain commands
TSR should only produce events that the blueprints are interested in consuming, by default TSR should be producing no events unless the blueprints have expressed interest in them.
This opt-in/subscription could be implemented in a few ways, but we believe an important aspect of this is to let TSR perform any needed filtering (potentially inside of the tsr device threads), so that we can avoid piping numerous events back to sofie-core/blueprints before the irrelevent events can be discarded.
To achieve this, we propose that this should be defined by a new property produced alongside the rundown and rundown-baseline during ingest. Sofie will pipe this to TSR as the activate rundown changes to update the subscription. (It should also be possible to use this with the studio baseline, which may be future scope and not implemented by us)
I think there are a couple of approaches that could be taken with this. I do not know which is best at this stage, and would appreciate any input on both the implications from the perspective of blueprints or tsr.
A: Link these events to the layers/mappings
Each event will look something like:
interface TSRStateEvent {
type: 'tsr'
deviceId: string // eg atem0
deviceType: DeviceType
layerId: string // The mapping it corresponds to
eventPath: string // the 'programInput'
eventPayload: unknown
}
The payload and path properties will want to be strongly typed, meaning this interface may need to become a type union to make that possible
During ingest for a rundown, the blueprints should be able to declare their desire to ‘subscribe’ to events such as with:
const tsrStateSubscriptions = [
{
deviceId: 'atem0',
layerId: 'atem_me_program', // The mapping
eventPath: 'programInput',
}
]
Note: these types are a rough sketch, and are not yet fully formed.
My concern here is that the current implementation of shared control does not link states back to mappings, and a particular address could be influenced by multiple mappings/layers.
B: Use the shared control addresses
Each event will look something like:
interface TSRStateEvent {
type: 'tsr'
deviceId: string // eg atem0
deviceType: DeviceType
eventAddress: string // the 'shared control address', or somethins like `me-program.1` ?
eventPayload: unknown
}
And subscription
const tsrStateSubscriptions = [
{
deviceId: 'atem0',
eventAddress: 'me-program.{{ mappings.atem_me_program.index }}', // Interpolated with options from mappings
}
]
It may be desirable to support wildcards/globs in the paths, or that may be future scope.
My concern here is that it puts the work of translating state addresses to mappings on the blueprints, but this might be fine or even beneficial as some states may not perfectly map to a single mapping anyway.
Consuming events
I think that this would be best handled by a new adlib-action like blueprint method. That would allow blueprints to easily apply changes to the current and next partinstances based on this state, using familiar methods and workflows.
But it is possible that this wont be enough, and more changes may want to be made to the rundown. For this, I would propose that this blueprint method can dispatch an ingest update that will be received as a new ‘change’ type in processIngestData. This then allows ingest blueprints to process the change however it likes, again in a process that doesn’t invent much here.
Getting the events from playout-gateway to the blueprints sounds simple, as we already have the bidirectional ddp flow, so playout-gateway will be able to dispatch events to be processed by the blueprints.
Sofie-core should perform a debounce/queue of these events, and batch them so that bursts of events don’t cause a queue of handlers. Instead the blueprints should expect to receive an array of batched events.
Future scope
While this RFC is focused on events from TSR devices, it is reasonable that in the future it may be desirable to add some other event source. The types, naming and structure should reflect this and try not to be too TSR specific. The event type itself will likely want to be a union, so that additional types can be added to it in the future.
In the future, it may be desirable to have more filtering of events based on the eventPayload, but we see this as an optimisation stage that can be added later.
Process
The Sofie Team will evaluate this RFC and open up a discussion about it, usually within a week.
About Me
This RFC is posted on behalf of the BBC.
Use Case
As an extension of shared control it would be good to have a blueprint method that can respond to changes in the playout devices.
This method should be able to modify current and upcoming parts (potentially the whole running order?)
A sub-task of this would be to able to implement this feedback mechanism in response to HTTP response Body's in the HTTPSend and HTTPListen device.
Proposal
Note: My knowledge of shared control is limited, I believe it operates entirely inside TSR so isn’t something that sofie-core can directly build upon.
Producing events in TSR
I believe there are a few types of events that we will care about:
TSR should only produce events that the blueprints are interested in consuming, by default TSR should be producing no events unless the blueprints have expressed interest in them.
This opt-in/subscription could be implemented in a few ways, but we believe an important aspect of this is to let TSR perform any needed filtering (potentially inside of the tsr device threads), so that we can avoid piping numerous events back to sofie-core/blueprints before the irrelevent events can be discarded.
To achieve this, we propose that this should be defined by a new property produced alongside the rundown and rundown-baseline during ingest. Sofie will pipe this to TSR as the activate rundown changes to update the subscription. (It should also be possible to use this with the studio baseline, which may be future scope and not implemented by us)
I think there are a couple of approaches that could be taken with this. I do not know which is best at this stage, and would appreciate any input on both the implications from the perspective of blueprints or tsr.
A: Link these events to the layers/mappings
Each event will look something like:
The payload and path properties will want to be strongly typed, meaning this interface may need to become a type union to make that possible
During ingest for a rundown, the blueprints should be able to declare their desire to ‘subscribe’ to events such as with:
Note: these types are a rough sketch, and are not yet fully formed.
My concern here is that the current implementation of shared control does not link states back to mappings, and a particular address could be influenced by multiple mappings/layers.
B: Use the shared control addresses
Each event will look something like:
And subscription
It may be desirable to support wildcards/globs in the paths, or that may be future scope.
My concern here is that it puts the work of translating state addresses to mappings on the blueprints, but this might be fine or even beneficial as some states may not perfectly map to a single mapping anyway.
Consuming events
I think that this would be best handled by a new adlib-action like blueprint method. That would allow blueprints to easily apply changes to the current and next partinstances based on this state, using familiar methods and workflows.
But it is possible that this wont be enough, and more changes may want to be made to the rundown. For this, I would propose that this blueprint method can dispatch an ingest update that will be received as a new ‘change’ type in processIngestData. This then allows ingest blueprints to process the change however it likes, again in a process that doesn’t invent much here.
Getting the events from playout-gateway to the blueprints sounds simple, as we already have the bidirectional ddp flow, so playout-gateway will be able to dispatch events to be processed by the blueprints.
Sofie-core should perform a debounce/queue of these events, and batch them so that bursts of events don’t cause a queue of handlers. Instead the blueprints should expect to receive an array of batched events.
Future scope
While this RFC is focused on events from TSR devices, it is reasonable that in the future it may be desirable to add some other event source. The types, naming and structure should reflect this and try not to be too TSR specific. The event type itself will likely want to be a union, so that additional types can be added to it in the future.
In the future, it may be desirable to have more filtering of events based on the eventPayload, but we see this as an optimisation stage that can be added later.
Process
The Sofie Team will evaluate this RFC and open up a discussion about it, usually within a week.