You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: packages/documentation/docs/for-developers/data-model.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,7 +18,7 @@ In every case, any layout changes and any scheduled cleanup are performed by the
18
18
19
19
This category of collections is rather loosely defined, as it ends up being everything that doesn't belong somewhere else
20
20
21
-
This consists of anything that is configurable from the Sofie UI, anything needed soley for the UI and some other bits. Additionally, there are some collections which are populated by other portions of a Sofie system, such as by Package Manager, through an API over DDP.
21
+
This consists of anything that is configurable from the Sofie UI, anything needed solely for the UI and some other bits. Additionally, there are some collections which are populated by other portions of a Sofie system, such as by Package Manager, through an API over DDP.
22
22
Currently, there is not a very clearly defined flow for modifying these documents, with the UI often making changes directly with minimal or no validation.
23
23
24
24
This includes:
@@ -81,7 +81,7 @@ Some of these collections are used by Package Manager to initiate work, while ot
81
81
82
82
This category of collections is owned by the playout [worker threads](./worker-threads-and-locks.md), and is used to model the playout of a Rundown or set of Rundowns.
83
83
84
-
During the final stage of an ingest operation, there is a period where the ingest worker aquires a `PlaylistLock`, so that it can ensure that the RundownPlaylist the Rundown is a part of is updated with any necessary changes following the ingest operation. During this lock, it will also attempt to [sync any ingest changes](./for-blueprint-developers/sync-ingest-changes) to the PartInstances and PieceInstances, if supported by the blueprints.
84
+
During the final stage of an ingest operation, there is a period where the ingest worker acquires a `PlaylistLock`, so that it can ensure that the RundownPlaylist the Rundown is a part of is updated with any necessary changes following the ingest operation. During this lock, it will also attempt to [sync any ingest changes](./for-blueprint-developers/sync-ingest-changes) to the PartInstances and PieceInstances, if supported by the blueprints.
85
85
86
86
As before, Meteor is allowed to write to these collections as part of migrations, and cleaning up old documents.
87
87
@@ -100,7 +100,7 @@ These collections are used in combination with many of the ingest collections, t
100
100
RundownPlaylists are a Sofie invention designed to solve one problem; in some NRCS it is beneficial to build a show across multiple Rundowns, which should then be concatenated for playout.
101
101
In particular, MOS has no concept of a Playlist, only Rundowns, and it was here where we need to be able to combine multiple Rundowns.
102
102
103
-
This functionality can be used to either break down long shows into managable chunks, or to indicate a different type of show between the each portion.
103
+
This functionality can be used to either break down long shows into manageable chunks, or to indicate a different type of show between the each portion.
104
104
105
105
Because of this, RundownPlaylists are largely missing from the ingest side of Sofie. We do not expose them in the ingest APIs, or do anything with them throughout the majority of the blueprints generating a Rundown.
106
106
Instead, we let the blueprints specify that a Rundown should be part of a RundownPlaylist by setting the `playlistExternalId` property, where multiple Rundowns in a Studio with the same id will be grouped into a RundownPlaylist.
@@ -126,6 +126,6 @@ Our solution to some of this early on was to not regenerate certain Parts when r
126
126
127
127
At this point in time, Adlib Actions did not exist in Sofie. They are able to change almost every property of a Part of Piece that ingest is able to define, which makes the resetting process harder.
128
128
129
-
PartInstances and PieceInstances were added as a way for us to make a copy of each Part and Piece, as it was selected for playout, so that we could allow ingest without risking affecting playout, and to simplify the cleanup performed. The PartInstances and PieceInstances are our record of how the Rundown was played, which we can utilise to output metadata such as for chapter markers on a web player. In earlier versions of Sofie this was tracked independently with an `AsRunLog`, which resulted in odd issues such as having `AsRunLog` entries which refered to a Part which no longer existed, or whose content was very different to how it was played.
129
+
PartInstances and PieceInstances were added as a way for us to make a copy of each Part and Piece, as it was selected for playout, so that we could allow ingest without risking affecting playout, and to simplify the cleanup performed. The PartInstances and PieceInstances are our record of how the Rundown was played, which we can utilise to output metadata such as for chapter markers on a web player. In earlier versions of Sofie this was tracked independently with an `AsRunLog`, which resulted in odd issues such as having `AsRunLog` entries which referred to a Part which no longer existed, or whose content was very different to how it was played.
130
130
131
131
Later on, this separation has allowed us to more cleanly define operations as ingest or playout, and allows us to run them in parallel with more confidence that they won't accidentally wipe out each others changes. Previously, both ingest and playout operations would be modifying documents in the Piece and Part collections, making concurrent operations unsafe as they could be modifying the same Part or Piece.
Copy file name to clipboardExpand all lines: packages/documentation/docs/for-developers/device-integrations/intro.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Introduction
2
2
3
-
Device integrations in Sofie are part of the Timeline State Resolver (TSR) library. A device integration has a couple of responsibilites in the Sofie eco system. First and foremost it should establish a connection with a foreign device. It should also be able to convert Sofie's idea of what the device should be doing into commands to control the device. And lastly it should export interfaces to be used by the blueprints developer.
3
+
Device integrations in Sofie are part of the Timeline State Resolver (TSR) library. A device integration has a couple of responsibilities in the Sofie eco system. First and foremost it should establish a connection with a foreign device. It should also be able to convert Sofie's idea of what the device should be doing into commands to control the device. And lastly it should export interfaces to be used by the blueprints developer.
4
4
5
5
In order to understand all about writing TSR integrations there are some concepts to familiarise yourself with, in this documentation we will attempt to explain these.
6
6
@@ -9,9 +9,9 @@ In order to understand all about writing TSR integrations there are some concept
9
9
-[TSR Types package](./tsr-types.html)
10
10
-[TSR Actions](./tsr-actions.html)
11
11
12
-
But to start of we will explain the general structure of the TSR. Any user of the TSR will interface primarily with the Conductor class. Primarily the user will input device configurations, mappings and timelines into the TSR. The timeline describes the entire state of all of the devices over time. It does this by putting objects on timeline layers. Every timeline layer maps to a specific part of the device, this is configured throught the mappings.
12
+
But to start off we will explain the general structure of the TSR. Any user of the TSR will interface primarily with the Conductor class. Primarily the user will input device configurations, mappings and timelines into the TSR. The timeline describes the entire state of all of the devices over time. It does this by putting objects on timeline layers. Every timeline layer maps to a specific part of the device, this is configured through the mappings.
13
13
14
-
The timeline is converted into disctinct states at different points in time, and these states are fed to the individual integrations. As an integration developer you shouldn't have to worry about keeping track of this. It is most important that you expose \(a\) a method to convert from a Timeline State to a Device State, \(b\) a method for diffing 2 device states and (c) a way to send commands to the device. We'll dive deeper into this in [TSR Integration API](./tsr-api.html).
14
+
The timeline is converted into disctinct states at different points in time, and these states are fed to the individual integrations. As an integration developer you shouldn't have to worry about keeping track of this. It is most important that you expose \(a\) a method to convert from a Timeline State to a Device State, \(b\) a method for diffing 2 device states and \(c\) a way to send commands to the device. We'll dive deeper into this in [TSR Integration API](./tsr-api.html).
15
15
16
16
:::info
17
17
The information in this section is not a conclusive guide on writing an integration, it should be use more as a guide to use while looking at a TSR integration such as the [OSC integration](https://github.com/Sofie-Automation/sofie-timeline-state-resolver/tree/master/packages/timeline-state-resolver/src/integrations/osc).
Copy file name to clipboardExpand all lines: packages/documentation/docs/for-developers/for-blueprint-developers/lookahead.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -38,7 +38,7 @@ export enum LookaheadMode {
38
38
}
39
39
```
40
40
41
-
If undefined, `lookaheadMaxSearchDistance` currently has a default distance of 10 parts. This number was chosen arbitrarily, and could change in the future. Be careful when choosing a distance to not set it too high. All the Pieces from the parts being searched have to be loaded from the database, which can come at a noticable cost.
41
+
If undefined, `lookaheadMaxSearchDistance` currently has a default distance of 10 parts. This number was chosen arbitrarily, and could change in the future. Be careful when choosing a distance to not set it too high. All the Pieces from the parts being searched have to be loaded from the database, which can come at a noticeable cost.
42
42
43
43
If you are doing [AB Playback](./ab-playback.md), or performing some other processing of the timeline in `onTimelineGenerate`, you may benefit from increasing the value of `lookaheadDepth`. In the case of AB Playback, you will likely want to set it to the number of players available in your pool.
Copy file name to clipboardExpand all lines: packages/documentation/docs/for-developers/for-blueprint-developers/manipulating-ingest-data.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ At times it can be useful to manipulate this data before it gets passed into the
7
7
8
8
A new method `processIngestData` was added to transform the `NRCSIngestRundown` into a `SofieIngestRundown`. The types of the two are the same, so implementing the `processIngestData` method is optional, with the default being to pass through the NRCS rundown unchanged. (There is an exception here for MOS, which is explained below).
9
9
10
-
The basic implementation of this method which simply propogates nrcs changes is:
10
+
The basic implementation of this method which simply propagates nrcs changes is:
Copy file name to clipboardExpand all lines: packages/documentation/docs/for-developers/for-blueprint-developers/part-and-piece-timings.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -131,7 +131,7 @@ const inTransition = {
131
131
132
132
Pieces with an infinite lifespan (ie, not `lifespan: PieceLifespan.WithinPart`) get handled differently to other pieces.
133
133
134
-
Only one pieceGoup is created for an infinite Piece which is present in multiple of the current, next and previous Parts.
134
+
Only one pieceGroup is created for an infinite Piece which is present in multiple of the current, next and previous Parts.
135
135
The Piece calculates and tracks its own started playback times, which is preserved and reused in future takes. On the timeline it lives outside of the partGroups, but still gets the same caps applied when appropriate.
Copy file name to clipboardExpand all lines: packages/documentation/docs/for-developers/for-blueprint-developers/sync-ingest-changes.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,11 +2,11 @@
2
2
title: Sync Ingest Changes
3
3
---
4
4
5
-
Since PartInstances and PieceInstances were added to Sofie, the default behaviour in Sofie is to not propogate any ingest changes from a Part onto its PartInstances.
5
+
Since PartInstances and PieceInstances were added to Sofie, the default behaviour in Sofie is to not propagate any ingest changes from a Part onto its PartInstances.
6
6
7
-
This is a safety net as without a detailed understanding of the Part and the change, we can't know whether it is safe to make on air. Without this, it would be possible for the user to change a clip name in the NRCS, and for Sofie to happily propogate that could result in a sudden change of clip mid sentence, or black if the clip needed to be copied to the playout server. This gets even more complicated when we consider that an adlib-action could have already modified a PartInstance, with changes that should likely not be overwritten with the newly ingested Part.
7
+
This is a safety net as without a detailed understanding of the Part and the change, we can't know whether it is safe to make on air. Without this, it would be possible for the user to change a clip name in the NRCS, and for Sofie to happily propagate that could result in a sudden change of clip mid sentence, or black if the clip needed to be copied to the playout server. This gets even more complicated when we consider that an adlib-action could have already modified a PartInstance, with changes that should likely not be overwritten with the newly ingested Part.
8
8
9
-
Instead, this propogation can be implemented by a ShowStyle blueprint in the `syncIngestUpdateToPartInstance` method, in this way the implementation can be tailored to understand the change and its potential impact. This method is able to update the previous, current and next PartInstances. Any PartInstances older than the previous is no longer being used on the timeline so is now simply a record of how it was played and updating it would have no benefit. Sofie never has any further than the next PartInstance generated, so for any Part after that the Part is all that exists for it, so any changes will be used when it becomes the next.
9
+
Instead, this propagation can be implemented by a ShowStyle blueprint in the `syncIngestUpdateToPartInstance` method, in this way the implementation can be tailored to understand the change and its potential impact. This method is able to update the previous, current and next PartInstances. Any PartInstances older than the previous is no longer being used on the timeline so is now simply a record of how it was played and updating it would have no benefit. Sofie never has any further than the next PartInstance generated, so for any Part after that the Part is all that exists for it, so any changes will be used when it becomes the next.
10
10
11
11
In this blueprint method, you are able to update almost any of the properties that are available to you both during ingest, and during adlib actions. It is possible the leave the Part in a broken state after this, so care must be taken to ensure it is not. If the call to your method throws an uncaught error, the changes you have made so far will be discarded but the rest of the ingest operation will continue as normal.
Copy file name to clipboardExpand all lines: packages/documentation/docs/for-developers/for-blueprint-developers/timeline-datastore.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Timeline Datastore
2
2
3
-
The timeline datastore is a key-value store that can be used in conjuction with the timeline. The benefit of modifying values in the datastore is that the timings in the timeline are not modified so we can skip a lot of complicated calculations which reduces the system response time. An example usecase of the datastore feature is a fastpath for cutting cameras.
3
+
The timeline datastore is a key-value store that can be used in conjunction with the timeline. The benefit of modifying values in the datastore is that the timings in the timeline are not modified so we can skip a lot of complicated calculations which reduces the system response time. An example usecase of the datastore feature is a fastpath for cutting cameras.
Copy file name to clipboardExpand all lines: packages/documentation/docs/for-developers/mos-plugins.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ title: MOS-plugins
4
4
5
5
# iFrames MOS-plugins
6
6
7
-
**The usage of MOS-plugins allow micro frontends to be injected into Sofie for the purpuse of adding content to the production without turning away from the Sofie UI.**
7
+
**The usage of MOS-plugins allow micro frontends to be injected into Sofie for the purpose of adding content to the production without turning away from the Sofie UI.**
8
8
9
9
Example use cases can be browsing and playing clips straight from a video server, or the creation of lower third graphics without storing it in the NRCS.
10
10
@@ -26,7 +26,7 @@ The user can create one or more Buckets. From the plugin they can drag-and-drop
26
26
## Cross-origin drag-and-drop
27
27
28
28
:::note Bucket workflow without drag-and-drop
29
-
The plugin iFrame can send a `postMessage` call with an `ncsItem` payload to programatically create an ncsItem without the drag-and-drop interaction. This is a viable solution which avoids cross-origin drag-and-drop problems.
29
+
The plugin iFrame can send a `postMessage` call with an `ncsItem` payload to programmatically create an ncsItem without the drag-and-drop interaction. This is a viable solution which avoids cross-origin drag-and-drop problems.
30
30
:::
31
31
32
32
### The problem
@@ -60,10 +60,10 @@ As you can tell from the table, you need to exactly match both the protocol, dom
60
60
61
61
_The proxy idea_ is to use rewrite-rules in a proxy server (e.g. NGINX) to serve the plugin from a path on the Sofie server's domain. As this can't be done as subdomains, that leaves the option of having a folder underneath the top level of the Sofie server's domain.
62
62
63
-
An example of this would be to serve Sofie at `https://mysofie.com` and then host the plugin (directly or via a proxy) at `https://mysofie.com/myplugin`. Technically this will work, but this solution is fragile. All links within the plugin will have to be either absolute or truly relative links that take the URL structure into account. This is doable if the plugin is being developed with this in mind. But it leads to a fragile tight coupling between the plugin and the host application (Sofie) which can break with any inconsiderate udate in the future.
63
+
An example of this would be to serve Sofie at `https://mysofie.com` and then host the plugin (directly or via a proxy) at `https://mysofie.com/myplugin`. Technically this will work, but this solution is fragile. All links within the plugin will have to be either absolute or truly relative links that take the URL structure into account. This is doable if the plugin is being developed with this in mind. But it leads to a fragile tight coupling between the plugin and the host application (Sofie) which can break with any inconsiderate update in the future.
64
64
65
65
:::note Example of linking from a (potentially proxied) subfolder
66
-
**Case:**`https://mysofie.com/myplugin/index.html` wants to acccess`https://mysofie.com/myplugin/static/images/logo.png`.
66
+
**Case:**`https://mysofie.com/myplugin/index.html` wants to access`https://mysofie.com/myplugin/static/images/logo.png`.
67
67
68
68
Normally the plugin would be developed and bundled to work standalone, resulting in a link relative to its own base path, giving `/static/images/logo.png` which here wrongly resolves to `https://mysofie.com/static/images/logo.png`.
0 commit comments