requests.proto
syntax = "proto3";
import "models.proto";
import "google/protobuf/timestamp.proto";
option csharp_namespace = "TSS.Gateway.Sdk.Requests";
// Payload messages for the requests published on tss-requests-publish and the queries published on
// tss-api-publish, plus the Response envelope every query answer is wrapped in.
//
// Conventions used throughout:
// - Assets and scenes are addressed by either their uuid or their integration id (a oneof).
// - Positions and sizes are in pixels on the screen's canvas, origin at the bottom-left, y up.
// - Volumes and progress are normalized: 0 to 1.
// The envelope of every query response: either the error or the field matching the query.
message Response {
oneof response {
Error error = 1;
Ok Ok = 2;
StoryStatusResponse storyStatus = 3;
AvailableStoriesResponse availableStories = 4;
AvailableScenesResponse availableScenes = 5;
CurrentStateResponse currentState = 6;
InstanceInfo instanceInfo = 7;
CorruptedAssetsResponse corruptedAssets = 8;
StoryDataResponse storyData = 9;
AvailableStory availableStory = 10;
UrlAssetStreamAnswer urlAssetStreamAnswer = 11;
};
}
message Ok {
}
// The player rejected the request or query.
message Error {
string message = 1; // Human-readable reason.
int32 code = 2;
}
// Answer to story.status.
message StoryStatusResponse {
State status = 1;
string storyTitle = 2;
int32 storyVersion = 3;
int32 transitionDurationMs = 4; // Duration of the running scene transition, 0 outside one.
string storyUuid = 5;
}
// Answer to story.available-stories.
message AvailableStoriesResponse {
repeated AvailableStory stories = 1;
int32 count = 2; // Number of stories matching the search, before offset and limit are applied; the total to page through.
}
// One story that is synced to this player. Also the answer to story.available-story.
message AvailableStory {
string uuid = 1;
string name = 2;
string author = 3;
google.protobuf.Timestamp authoredAt = 4;
google.protobuf.Timestamp compiledAt = 5;
string description = 6;
AvailableStoryStatus status = 7;
google.protobuf.Timestamp lastPlayedAt = 8;
repeated int32 availableVersions = 9; // Versions on this player; StoryStartRequest.version must be one of these.
Thumbnails thumbnails = 10;
}
// Answer to story.available-scenes: the scenes of the running story.
message AvailableScenesResponse {
repeated AvailableScene scenes = 1;
optional string screensaverUuid = 2;
}
message AvailableScene {
string uuid = 1;
string title = 2;
Thumbnails thumbnails = 10;
}
message StoryStartRequest {
string storyUuid = 1;
optional int32 version = 2; // Specific version to start; absent starts the newest version on the player.
bool suppressPlaybackTracking = 3; // True skips the last-played bookkeeping, meant for automated smoke tests.
}
message VolumeChangeRequest {
float volume = 1; // Master volume, 0 to 1. Values outside that range are rejected.
}
// Answer to scene.status: the active scene and the current state of its assets.
message CurrentStateResponse {
Scene scene = 1;
repeated Asset assets = 2;
string storyTitle = 3;
float volume = 4; // Master volume, 0 to 1.
}
// Addresses the scene by uuid, integrationId, or sceneIndex. The screensaver scene is index 0, the
// other scenes count from 1 in story order; index 0 is an error when the story has no screensaver.
message SceneChangeRequest {
oneof scene {
string uuid = 1;
string integrationId = 2;
int32 sceneIndex = 3;
}
}
// Addresses one asset by uuid, or every asset carrying the integration id.
message AssetRequest{
oneof asset {
string uuid = 1;
string integrationId = 2;
}
}
message AssetSeekRequest {
oneof asset {
string uuid = 1;
string integrationId = 2;
}
float normalizedProgress = 3; // Target position in the media, 0 (start) to 1 (end).
}
message AssetVolumeChangeRequest {
oneof asset {
string uuid = 1;
string integrationId = 2;
}
float normalizedVolume = 3; // 0 to 1. Values outside that range are rejected.
}
// Moves the asset's bottom-left corner, in canvas pixels.
message AssetMoveRequest {
oneof asset {
string uuid = 1;
string integrationId = 2;
}
float left = 3;
float bottom = 4;
}
message AssetPageChangeRequest {
oneof asset {
string uuid = 1;
string integrationId = 2;
}
int32 page = 3; // Zero-based page index, 0 to pageCount - 1. Out-of-range values are rejected.
}
message AssetContentChangeRequest
{
oneof asset {
string uuid = 1;
string integrationId = 2;
}
string content = 3; // New text (text asset) or image uri (image asset). Rejected when it equals the current content.
}
// Crops the asset by moving its edges inward. Margins are pixels measured from the asset's
// original edges, must be 0 or positive, and fields left out keep their current value.
message AssetCropRequest {
oneof asset {
string uuid = 1;
string integrationId = 2;
}
optional int32 left = 3;
optional int32 top = 4;
optional int32 right = 5;
optional int32 bottom = 6;
}
// Animates the asset to a new rectangle over animationTimeInMs. Fields left out keep their
// current value. Position and size in canvas pixels, x/y is the bottom-left corner.
message AssetAnimateRectRequest {
oneof asset {
string uuid = 1;
string integrationId = 2;
}
optional float height = 3;
optional float width = 4;
optional float x = 5;
optional float y = 6;
int32 animationTimeInMs = 7;
}
// Resizes and/or repositions the asset immediately. Fields left out keep their current value.
// Position and size in canvas pixels, left/bottom is the bottom-left corner.
message AssetResizeRequest {
oneof asset {
string uuid = 1;
string integrationId = 2;
}
optional float left = 3;
optional float bottom = 4;
optional float width = 5;
optional float height = 6;
}
message UrlAssetInputRequest{
oneof asset {
string uuid = 1;
string integrationId = 2;
}
string key = 3; // The key to send to the page, a character or a key name such as "Enter".
}
message UrlAssetTouchRequest{
oneof asset {
string uuid = 1;
string integrationId = 2;
}
UrlTouch touch = 3;
}
// Loads another page in a url asset for the rest of the scene. The authored url stays the asset's
// home, so back and home still return to it, and leaving the scene restores it.
message AssetUrlChangeRequest {
oneof asset {
string uuid = 1;
string integrationId = 2;
}
string url = 3; // Rejected when it is not a http or https url, or when it is the page already loaded.
}
// Query asset.stream-offer: starts a WebRTC stream of a URL asset for one viewer, sent straight to the
// viewer over the local network; the gateway only carries the handshake. The stream is H.264 at up to
// 30 fps without audio. It keeps the asset's aspect ratio and fits in maxWidth x maxHeight, never above
// the asset's own size, 3840 on either side or the pixel count of 3840x2160.
// The player runs up to maxUrlStreams streams at a time (default 4), over all its URL assets, and
// rejects the offer with code 716 once that limit is reached. A stream ends when the asset unloads, on
// asset.stream-stop, or a few seconds after the viewer disappears.
message UrlAssetStreamOfferRequest {
string uuid = 1; // One asset only, so there is no integration id.
string sdp = 2; // Complete offer SDP with ICE gathering finished; candidates are not sent separately.
optional int32 maxWidth = 3; // Largest size the viewer shows the stream at, in device pixels; absent leaves it to the other limits.
optional int32 maxHeight = 4;
optional int32 maxBitrateKbps = 5; // Encoder bitrate cap; absent scales with the stream size, 8000 at 1920x1080 up to 30000 at 3840x2160.
}
// Answer to asset.stream-offer.
message UrlAssetStreamAnswer {
string sdp = 1; // Complete answer SDP with ICE gathering finished.
string sessionId = 2; // Identifies this viewer's stream; asset.stream-resize and asset.stream-stop take it.
}
// Request asset.stream-resize: the room the viewer shows the stream in changed. The player changes the
// running stream's size, and its bitrate cap when the offer set none, without a new offer. Resizes
// closer together than half a second are applied once, with the latest size.
message UrlAssetStreamResizeRequest {
string uuid = 1; // The streamed asset.
string sessionId = 2; // From UrlAssetStreamAnswer.
int32 maxWidth = 3; // In device pixels, same rules as UrlAssetStreamOfferRequest.
int32 maxHeight = 4;
}
// Request asset.stream-stop: stops one viewer's stream; other viewers of the asset keep streaming.
message UrlAssetStreamStopRequest {
string uuid = 1; // The streamed asset.
string sessionId = 2; // From UrlAssetStreamAnswer.
}
message TriggerFireRequest {
string triggerUuid = 1;
optional bool state = 2; // For toggle actions: true forces show, false forces hide, absent toggles.
string sourceAssetUuid = 3; // The pressed asset when the player fires an on-click trigger; empty for other firers.
string sourceAssetIntegrationId = 4;
}
// Answer to instance.info.
message InstanceInfo {
string screenName = 1;
string setupName = 2;
int32 width = 3; // Screen resolution in pixels.
int32 height = 4;
string setupUuid = 5;
int32 screenId = 6;
}
// Answer to story.corrupted-assets: assets of the running story that failed to load, per scene.
message CorruptedAssetsResponse {
repeated CorruptedScene scenes = 1;
}
message CorruptedScene {
string uuid = 1;
string integrationId = 2;
string name = 3;
repeated CorruptedAsset assets = 4;
int32 index = 5; // Zero-based position of the scene in the story's scene order.
}
message CorruptedAsset {
string uuid = 1;
string integrationId = 2;
string name = 3;
int32 code = 4; // Player error code describing why the asset failed to load.
CorruptedAssetType type = 5;
}
message StoryDataRequest {
string uuid = 1;
int32 version = 2;
}
// Answer to story.data: the full story structure, see models.proto.
message StoryDataResponse {
Story story = 1;
}
enum CorruptedAssetType
{
UNDEFINED = 0;
VIDEO = 1;
IMAGE = 2;
TEXT = 3;
SOUND = 4;
URL = 5;
NDI = 6;
PDF = 7;
}
// Query for story.available-stories.
message AvailableStoriesRequest {
SortDirection sortDir = 1;
StorySortBy sortBy = 2;
string search = 3; // Filters on the story name, description and author, tolerating typos and partial words; "quoted text" matches as a phrase. Empty returns every story.
int32 offset = 4;
int32 limit = 5; // Maximum number of stories returned. The protobuf default of 0 returns none, so always set it.
}
message AvailableStoryRequest {
string uuid = 1;
}
enum AvailableStoryStatus
{
UNKNOWN = 0;
INITIALIZING = 1;
READY = 2;
IN_USE = 3;
INITIALIZATION_ERROR = 4;
DRAFT = 5;
UPDATING = 6;
}
// Playback state of the player.
enum State
{
NONE = 0;
STARTING = 1;
RUNNING = 2;
CLOSING = 3;
TRANSITIONING = 4;
ERROR = 5;
PREPARING_TRANSITION = 6;
}
enum SortDirection
{
ASC = 0;
DESC = 1;
}
enum StorySortBy
{
NAME = 0;
AUTHOR = 1;
AUTHORED_AT = 2;
COMPILED_AT = 3;
LAST_PLAYED_AT = 4;
}