diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c57b5b..330b9d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,4 +161,9 @@ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ui/dist/" OPTIONAL ) +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/docs/" + DESTINATION "docs" + OPTIONAL +) + source_group(TREE "${APP_DIR}" FILES ${APP_SOURCES}) diff --git a/docs/openapi.yaml b/docs/openapi.yaml new file mode 100644 index 0000000..dc8db5f --- /dev/null +++ b/docs/openapi.yaml @@ -0,0 +1,503 @@ +openapi: 3.0.3 +info: + title: Video Shader Toys Control API + version: 0.1.0 + description: | + REST API exposed by the local Video Shader Toys control server. + + The API is intended for local control tools and the bundled React UI. All mutating + endpoints return a small action result object. Successful mutating requests also + broadcast the latest runtime state over the `/ws` WebSocket. + + WebSocket state streaming is not described by OpenAPI; connect to `ws://127.0.0.1:{port}/ws` + to receive full runtime state JSON messages whenever state changes. +servers: + - url: http://127.0.0.1:8080 + description: Default local control server +tags: + - name: State + description: Runtime state and status. + - name: Layers + description: Layer stack control. + - name: Stack Presets + description: Save and recall layer stack presets. + - name: Runtime + description: Runtime actions. +paths: + /api/state: + get: + tags: [State] + summary: Get current runtime state + operationId: getRuntimeState + responses: + "200": + description: Current runtime state. + content: + application/json: + schema: + $ref: "#/components/schemas/RuntimeState" + /api/layers/add: + post: + tags: [Layers] + summary: Add a layer using a shader package + operationId: addLayer + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/AddLayerRequest" + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" + /api/layers/remove: + post: + tags: [Layers] + summary: Remove a layer + operationId: removeLayer + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/LayerIdRequest" + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" + /api/layers/move: + post: + tags: [Layers] + summary: Move a layer by direction + description: Moves a layer up or down by one or more positions, depending on the signed direction value. + operationId: moveLayer + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/MoveLayerRequest" + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" + /api/layers/reorder: + post: + tags: [Layers] + summary: Move a layer to an absolute index + operationId: reorderLayer + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ReorderLayerRequest" + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" + /api/layers/set-bypass: + post: + tags: [Layers] + summary: Set layer bypass state + operationId: setLayerBypass + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/SetBypassRequest" + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" + /api/layers/set-shader: + post: + tags: [Layers] + summary: Change the shader package used by a layer + operationId: setLayerShader + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/SetShaderRequest" + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" + /api/layers/update-parameter: + post: + tags: [Layers] + summary: Update a layer parameter value + operationId: updateLayerParameter + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/UpdateParameterRequest" + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" + /api/layers/reset-parameters: + post: + tags: [Layers] + summary: Reset a layer's parameters to shader defaults + operationId: resetLayerParameters + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/LayerIdRequest" + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" + /api/stack-presets/save: + post: + tags: [Stack Presets] + summary: Save the current layer stack as a preset + operationId: saveStackPreset + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/PresetNameRequest" + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" + /api/stack-presets/load: + post: + tags: [Stack Presets] + summary: Load a layer stack preset + operationId: loadStackPreset + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/PresetNameRequest" + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" + /api/reload: + post: + tags: [Runtime] + summary: Reload shaders + operationId: reloadShaders + requestBody: + required: false + content: + application/json: + schema: + type: object + additionalProperties: false + responses: + "200": + $ref: "#/components/responses/ActionOk" + "400": + $ref: "#/components/responses/ActionError" +components: + responses: + ActionOk: + description: Action succeeded. + content: + application/json: + schema: + $ref: "#/components/schemas/ActionResponse" + example: + ok: true + ActionError: + description: Action failed or request JSON was invalid. + content: + application/json: + schema: + $ref: "#/components/schemas/ActionResponse" + example: + ok: false + error: Unknown layer id. + schemas: + ActionResponse: + type: object + required: [ok] + properties: + ok: + type: boolean + error: + type: string + description: Present when the request fails or when the runtime returns a diagnostic. + additionalProperties: false + AddLayerRequest: + type: object + required: [shaderId] + properties: + shaderId: + type: string + example: studio-color + additionalProperties: false + LayerIdRequest: + type: object + required: [layerId] + properties: + layerId: + type: string + example: layer-1 + additionalProperties: false + MoveLayerRequest: + type: object + required: [layerId, direction] + properties: + layerId: + type: string + direction: + type: integer + description: Signed movement direction. Negative moves toward the top of the stack; positive moves toward the bottom. + example: -1 + additionalProperties: false + ReorderLayerRequest: + type: object + required: [layerId, targetIndex] + properties: + layerId: + type: string + targetIndex: + type: integer + minimum: 0 + example: 0 + additionalProperties: false + SetBypassRequest: + type: object + required: [layerId, bypass] + properties: + layerId: + type: string + bypass: + type: boolean + additionalProperties: false + SetShaderRequest: + type: object + required: [layerId, shaderId] + properties: + layerId: + type: string + shaderId: + type: string + example: vhs + additionalProperties: false + UpdateParameterRequest: + type: object + required: [layerId, parameterId, value] + properties: + layerId: + type: string + parameterId: + type: string + example: brightness + value: + description: Parameter value. Type depends on the shader parameter definition. + oneOf: + - type: number + - type: boolean + - type: string + - type: array + items: + type: number + example: 1.25 + additionalProperties: false + PresetNameRequest: + type: object + required: [presetName] + properties: + presetName: + type: string + example: live-show-look + additionalProperties: false + RuntimeState: + type: object + properties: + app: + $ref: "#/components/schemas/AppState" + runtime: + $ref: "#/components/schemas/RuntimeStatus" + video: + $ref: "#/components/schemas/VideoStatus" + decklink: + $ref: "#/components/schemas/DeckLinkStatus" + performance: + $ref: "#/components/schemas/PerformanceStatus" + shaders: + type: array + items: + $ref: "#/components/schemas/ShaderSummary" + stackPresets: + type: array + items: + type: string + layers: + type: array + items: + $ref: "#/components/schemas/LayerState" + AppState: + type: object + properties: + serverPort: + type: number + autoReload: + type: boolean + maxTemporalHistoryFrames: + type: number + enableExternalKeying: + type: boolean + videoFormat: + type: string + frameRate: + type: string + RuntimeStatus: + type: object + properties: + layerCount: + type: number + compileSucceeded: + type: boolean + compileMessage: + type: string + VideoStatus: + type: object + properties: + hasSignal: + type: boolean + width: + type: number + height: + type: number + modeName: + type: string + DeckLinkStatus: + type: object + properties: + modelName: + type: string + supportsInternalKeying: + type: boolean + supportsExternalKeying: + type: boolean + keyerInterfaceAvailable: + type: boolean + externalKeyingRequested: + type: boolean + externalKeyingActive: + type: boolean + statusMessage: + type: string + PerformanceStatus: + type: object + properties: + frameBudgetMs: + type: number + renderMs: + type: number + smoothedRenderMs: + type: number + budgetUsedPercent: + type: number + ShaderSummary: + type: object + properties: + id: + type: string + name: + type: string + description: + type: string + category: + type: string + temporal: + $ref: "#/components/schemas/TemporalState" + TemporalState: + type: object + properties: + enabled: + type: boolean + historySource: + type: string + enum: [source, preLayerInput, none] + requestedHistoryLength: + type: number + effectiveHistoryLength: + type: number + LayerState: + type: object + properties: + id: + type: string + shaderId: + type: string + shaderName: + type: string + bypass: + type: boolean + temporal: + $ref: "#/components/schemas/TemporalState" + parameters: + type: array + items: + $ref: "#/components/schemas/ParameterState" + ParameterState: + type: object + properties: + id: + type: string + label: + type: string + type: + type: string + enum: [float, vec2, color, bool, enum] + min: + type: array + items: + type: number + max: + type: array + items: + type: number + step: + type: array + items: + type: number + options: + type: array + items: + $ref: "#/components/schemas/ParameterOption" + value: + description: Current parameter value. + oneOf: + - type: number + - type: boolean + - type: string + - type: array + items: + type: number + ParameterOption: + type: object + properties: + value: + type: string + label: + type: string