diff --git a/.gitignore b/.gitignore index b267a7cd3..b3f74b548 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,9 @@ dist/* src/sdks/core/build/* src/sdks/core/dist/* src/sdks/core/test/transpiled-suite/* -src/sdks/discovery/build/* -src/sdks/discovery/dist/* -src/sdks/discovery/test/transpiled-suite/* +src/sdks/provider/build/* +src/sdks/provider/dist/* +src/sdks/provider/test/transpiled-suite/* src/sdks/manage/build/* src/sdks/manage/dist/* src/sdks/manage/test/transpiled-suite/* diff --git a/package-lock.json b/package-lock.json index a5dbae74d..83769136a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,8 @@ "license": "Apache-2.0", "workspaces": [ "src/sdks/core", - "src/sdks/manage" + "src/sdks/manage", + "src/sdks/provider" ], "bin": { "firebolt-version": "src/js/version.mjs" @@ -1136,6 +1137,10 @@ "node": ">=6" } }, + "node_modules/@firebolt-js/provider-sdk": { + "resolved": "src/sdks/provider", + "link": true + }, "node_modules/@firebolt-js/schemas": { "version": "1.0.0-next.0", "resolved": "https://registry.npmjs.org/@firebolt-js/schemas/-/schemas-1.0.0-next.0.tgz", @@ -16872,6 +16877,15 @@ "jest-environment-jsdom": "^28.1.3", "typescript": "^4.6.4" } + }, + "src/sdks/provider": { + "version": "0.16.0-next.3", + "license": "Apache-2.0", + "devDependencies": { + "jest": "^28.1.0", + "jest-environment-jsdom": "^28.1.3", + "typescript": "^4.6.4" + } } } } diff --git a/package.json b/package.json index 1c97344d2..1842caf03 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ }, "workspaces": [ "src/sdks/core", - "src/sdks/manage" + "src/sdks/manage", + "src/sdks/provider" ], "scripts": { "fs:setup": "npm run clean && mkdir -p dist", @@ -67,4 +68,4 @@ "sdk" ], "license": "Apache-2.0" -} +} \ No newline at end of file diff --git a/src/openrpc/broadcast_player.json b/src/openrpc/broadcast_player.json new file mode 100644 index 000000000..251ecec39 --- /dev/null +++ b/src/openrpc/broadcast_player.json @@ -0,0 +1,380 @@ +{ + "openrpc": "1.2.4", + "info": { + "title": "BroadcastPlayer", + "description": "A module for controlling and accessing media over broadcast", + "version": "0.0.0" + }, + "methods": [ + { + "name": "create", + "tags": [ + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:player:broadcast" + ] + }, + { + "name": "launch-provider" + } + ], + "summary": "Creates an instance of a player that can be used to play media over broadcast. Player instance that is created should also provide firebolt capability 'xrn:firebolt:capability:player:base'. If there is no provider running but there is a provider in the catalog, it will be launched.", + "params": [ + { + "name": "request", + "summary": "The create request", + "schema": { + "$ref": "#/components/schemas/BroadcastPlayerCreateRequest" + }, + "required": true + } + ], + "result": { + "name": "playerInstance", + "schema": { + "$ref": "#/components/schemas/BroadcastPlayerInstance" + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "request", + "value": {} + } + ], + "result": { + "name": "playerInstance", + "value": { + "playerId": "123", + "windowId": "456" + } + } + } + ] + }, + { + "name": "status", + "tags": [ + { + "name": "property:readonly" + }, + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:player:broadcast" + ] + } + ], + "summary": "Gets the latest broadcast status for the given player", + "params": [ + { + "name": "playerId", + "summary": "The id of the player to get the status for", + "schema": { + "type": "string" + }, + "required": true + } + ], + "result": { + "name": "playerStatus", + "schema": { + "$ref": "#/components/schemas/BroadcastPlayerStatus" + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "playerId", + "value": "app1:123" + } + ], + "result": { + "name": "playerStatus", + "value": { + "locked": false, + "frequency": 695000000, + "signalStrength": 90, + "signalQuality": 90 + } + } + }, + { + "name": "Default example #2", + "params": [ + { + "name": "playerId", + "value": "app2:456" + } + ], + "result": { + "name": "playerStatus", + "value": { + "locked": true, + "frequency": 695000000, + "signalStrength": 23, + "signalQuality": 55 + } + } + } + ] + }, + { + "name": "onRequestCreate", + "summary": "Registers as a provider for creating player instances", + "params": [], + "tags": [ + { + "name": "event", + "x-response": { + "$ref": "#/components/schemas/BroadcastPlayerInstance", + "examples": [ + { + "playerId": "123", + "windowId": "456" + } + ] + } + }, + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:broadcast", + "x-allow-focus": false + } + ], + "result": { + "name": "createRequest", + "summary": "The request to create a new player", + "schema": { + "$ref": "#/components/schemas/BroadcastPlayerCreateProviderRequest" + } + }, + "examples": [ + { + "name": "Default Example", + "params": [], + "result": { + "name": "Default Result", + "value": { + "correlationId": "abc", + "parameters": {} + } + } + } + ] + }, + { + "name": "onRequestStatus", + "summary": "Registers as a provider for when broadcast player status needs to be provided", + "params": [], + "tags": [ + { + "name": "event", + "x-response": { + "$ref": "#/components/schemas/BroadcastPlayerStatus", + "examples": [ + { + "locked": false, + "frequency": 695000000, + "signalStrength": 90, + "signalQuality": 90 + } + ] + } + }, + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:broadcast", + "x-allow-focus": false + } + ], + "result": { + "name": "statusRequest", + "summary": "The request to get the status of a player", + "schema": { + "$ref": "https://meta.comcast.com/firebolt/player#/definitions/PlayerProviderRequest" + } + }, + "examples": [ + { + "name": "Default Example", + "params": [], + "result": { + "name": "Default Result", + "value": { + "correlationId": "abc", + "parameters": { + "playerId": "123" + } + } + } + } + ] + }, + { + "name": "provideStatus", + "tags": [ + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:broadcast" + } + ], + "summary": "Tells listeners the current broadcast status of a player", + "params": [ + { + "name": "playerId", + "summary": "The id of the player the status is for", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "status", + "summary": "The status", + "schema": { + "$ref": "#/components/schemas/BroadcastPlayerStatus" + }, + "required": true + } + ], + "result": { + "name": "providedResponse", + "schema": { + "const": null + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "playerId", + "value": "123" + }, + { + "name": "status", + "value": { + "locked": false, + "frequency": 695000000, + "signalStrength": 90, + "signalQuality": 90 + } + } + ], + "result": { + "name": "providedResponse", + "value": null + } + } + ] + } + ], + "components": { + "schemas": { + "BroadcastPlayerCreateProviderRequest": { + "title": "BroadcastPlayerCreateProviderRequest", + "type": "object", + "required": [ + "correlationId", + "parameters" + ], + "properties": { + "correlationId": { + "type": "string", + "description": "An id to correlate the provider response with this request" + }, + "parameters": { + "description": "The request to load media in the player", + "$ref": "#/components/schemas/BroadcastPlayerCreateRequest" + } + }, + "examples": [ + {} + ] + }, + "BroadcastPlayerCreateRequest": { + "title": "BroadcastPlayerCreateRequest", + "type": "object", + "required": [], + "properties": {}, + "examples": [ + {} + ] + }, + "BroadcastPlayerInstance": { + "title": "BroadcastPlayerInstance", + "type": "object", + "required": [ + "playerId", + "windowId" + ], + "properties": { + "playerId": { + "description": "The id of player which can be used to load media or control the player", + "type": "string" + }, + "windowId": { + "description": "The id of window which will render the media in, can be used to control on screen where the media is shown", + "type": "string" + } + }, + "examples": [ + { + "playerId": "123", + "windowId": "456" + }, + { + "playerId": "abc", + "windowId": "def" + } + ] + }, + "BroadcastPlayerStatus": { + "title": "BroadcastPlayerStatus", + "type": "object", + "required": [ + "locked", + "frequency", + "signalStrength", + "signalQuality" + ], + "properties": { + "locked": { + "description": "Whether the current media has been locked", + "type": "boolean" + }, + "frequency": { + "description": "The signal frequency in hertz", + "type": "integer" + }, + "signalStrength": { + "description": "The strength of the signal from 0-100", + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "signalQuality": { + "description": "The quality of the signal from 0-100", + "type": "integer", + "minimum": 0, + "maximum": 100 + } + }, + "examples": [ + { + "locked": false, + "frequency": 1, + "signalStrength": 90, + "signalQuality": 90 + } + ] + } + } + } +} \ No newline at end of file diff --git a/src/openrpc/player.json b/src/openrpc/player.json new file mode 100644 index 000000000..26d23273b --- /dev/null +++ b/src/openrpc/player.json @@ -0,0 +1,814 @@ +{ + "openrpc": "1.2.4", + "info": { + "title": "Player", + "description": "A module for providing and using media player capabilities. This handles operations that would be associated with any player generically", + "version": "0.0.0" + }, + "methods": [ + { + "name": "load", + "tags": [ + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:player:base" + ] + } + ], + "summary": "Loads content in a player and starts a media session", + "params": [ + { + "name": "request", + "summary": "The load request", + "schema": { + "$ref": "#/components/schemas/PlayerLoadRequest" + }, + "required": true + } + ], + "result": { + "name": "mediaSession", + "schema": { + "$ref": "#/components/schemas/PlayerMediaSession" + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "request", + "value": { + "playerId": "app1:123", + "locator": "https://cdn.rdkcentral.com/media/assets/asset.hls" + } + } + ], + "result": { + "name": "mediaSession", + "value": { + "mediaSessionId": "sess1" + } + } + } + ] + }, + { + "name": "play", + "tags": [ + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:player:base" + ] + } + ], + "summary": "Starts playing the content that was last loaded", + "params": [ + { + "name": "playerId", + "summary": "The id of the player to start playing", + "schema": { + "type": "string" + }, + "required": true + } + ], + "result": { + "name": "playResponse", + "schema": { + "const": null + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "playerId", + "value": "app1:123" + } + ], + "result": { + "name": "playResponse", + "value": null + } + } + ] + }, + { + "name": "stop", + "tags": [ + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:player:base" + ] + } + ], + "summary": "Stops playing the content that was last loaded", + "params": [ + { + "name": "playerId", + "summary": "The id of the player to stop", + "schema": { + "type": "string" + }, + "required": true + } + ], + "result": { + "name": "stopResponse", + "schema": { + "const": null + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "playerId", + "value": "app1:123" + } + ], + "result": { + "name": "stopResponse", + "value": null + } + } + ] + }, + { + "name": "status", + "tags": [ + { + "name": "property:readonly" + }, + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:player:base" + ] + } + ], + "summary": "Gets the latest status for the given player", + "params": [ + { + "name": "playerId", + "summary": "The id of the player to get the status for", + "schema": { + "type": "string" + }, + "required": true + } + ], + "result": { + "name": "playerStatus", + "schema": { + "$ref": "#/components/schemas/PlayerStatus" + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "playerId", + "value": "app1:123" + } + ], + "result": { + "name": "playerStatus", + "value": { + "mediaSessionId": "sess1", + "state": "PLAYING" + } + } + }, + { + "name": "Default example #2", + "params": [ + { + "name": "playerId", + "value": "app2:456" + } + ], + "result": { + "name": "playerStatus", + "value": { + "mediaSessionId": "sess1", + "state": "BLOCKED", + "blockedReason": "CONTENT_NOT_FOUND" + } + } + } + ] + }, + { + "name": "progress", + "tags": [ + { + "name": "property:readonly" + }, + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:player:base" + ] + } + ], + "summary": "Gets the latest progress for the given player", + "params": [ + { + "name": "playerId", + "summary": "The id of the player to get the progress for", + "schema": { + "type": "string" + }, + "required": true + } + ], + "result": { + "name": "playerProgress", + "schema": { + "$ref": "#/components/schemas/PlayerProgress" + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "playerId", + "value": "app1:123" + } + ], + "result": { + "name": "playerProgress", + "value": { + "speed": 1, + "startPosition": 0, + "position": 5000, + "endPosition": 3600000, + "liveSyncTime": "2021-04-23T18:25:43.511Z" + } + } + }, + { + "name": "Default example #2", + "params": [ + { + "name": "playerId", + "value": "app2:456" + } + ], + "result": { + "name": "playerProgress", + "value": { + "speed": 3, + "startPosition": 5000, + "position": 10000, + "endPosition": 3600000, + "liveSyncTime": "2021-05-23T18:25:43.511Z" + } + } + } + ] + }, + { + "name": "onRequestLoad", + "summary": "Registers as a provider for when new media should be loaded into the player", + "params": [], + "tags": [ + { + "name": "event", + "x-response": { + "$ref": "#/components/schemas/PlayerMediaSession", + "examples": [ + { + "mediaSessionId": "sess1" + } + ] + } + }, + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:base", + "x-allow-focus": false + } + ], + "result": { + "name": "loadRequest", + "summary": "The request to load new media", + "schema": { + "$ref": "#/components/schemas/PlayerLoadProviderRequest" + } + }, + "examples": [ + { + "name": "Default Example", + "params": [], + "result": { + "name": "Default Result", + "value": { + "correlationId": "abc", + "parameters": { + "playerId": "app1:123", + "locator": "https://cdn.rdkcentral.com/media/assets/asset.hls" + } + } + } + } + ] + }, + { + "name": "onRequestPlay", + "summary": "Registers as a provider for when media should start playing", + "params": [], + "tags": [ + { + "name": "event", + "x-response": { + "$ref": "#/components/schemas/PlayerMediaSession", + "examples": [ + { + "mediaSessionId": "sess1" + } + ] + } + }, + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:base", + "x-allow-focus": false + } + ], + "result": { + "name": "playRequest", + "summary": "The request to start playing media", + "schema": { + "$ref": "https://meta.comcast.com/firebolt/player#/definitions/PlayerProviderRequest" + } + }, + "examples": [ + { + "name": "Default Example", + "params": [], + "result": { + "name": "Default Result", + "value": { + "correlationId": "abc", + "parameters": { + "playerId": "app1:123" + } + } + } + } + ] + }, + { + "name": "onRequestStop", + "summary": "Registers as a provider for when media should stop playing", + "params": [], + "tags": [ + { + "name": "event", + "x-response": { + "$ref": "#/components/schemas/PlayerMediaSession", + "examples": [ + { + "mediaSessionId": "sess1" + } + ] + } + }, + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:base", + "x-allow-focus": false + } + ], + "result": { + "name": "stopRequest", + "summary": "The request to stop playing media", + "schema": { + "$ref": "https://meta.comcast.com/firebolt/player#/definitions/PlayerProviderRequest" + } + }, + "examples": [ + { + "name": "Default Example", + "params": [], + "result": { + "name": "Default Result", + "value": { + "correlationId": "abc", + "parameters": { + "playerId": "app1:123" + } + } + } + } + ] + }, + { + "name": "onRequestStatus", + "summary": "Registers as a provider for when player status needs to be provided", + "params": [], + "tags": [ + { + "name": "event", + "x-response": { + "$ref": "#/components/schemas/PlayerStatus", + "examples": [ + { + "mediaSessionId": "sess1", + "state": "IDLE" + } + ] + } + }, + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:base", + "x-allow-focus": false + } + ], + "result": { + "name": "statusRequest", + "summary": "The request to get the status of a player", + "schema": { + "$ref": "https://meta.comcast.com/firebolt/player#/definitions/PlayerProviderRequest" + } + }, + "examples": [ + { + "name": "Default Example", + "params": [], + "result": { + "name": "Default Result", + "value": { + "correlationId": "abc", + "parameters": { + "playerId": "123" + } + } + } + } + ] + }, + { + "name": "onRequestProgress", + "summary": "Registers as a provider for when player progress needs to be provided", + "params": [], + "tags": [ + { + "name": "event", + "x-response": { + "$ref": "#/components/schemas/PlayerProgress", + "examples": [ + { + "speed": 1, + "startPosition": 0, + "position": 5000, + "endPosition": 3600000, + "liveSyncTime": "2021-04-23T18:25:43.511Z" + } + ] + } + }, + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:base", + "x-allow-focus": false + } + ], + "result": { + "name": "progressRequest", + "summary": "The request to stop playing media", + "schema": { + "$ref": "https://meta.comcast.com/firebolt/player#/definitions/PlayerProviderRequest" + } + }, + "examples": [ + { + "name": "Default Example", + "params": [], + "result": { + "name": "Default Result", + "value": { + "correlationId": "abc", + "parameters": { + "playerId": "123" + } + } + } + } + ] + }, + { + "name": "provideStatus", + "tags": [ + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:base" + } + ], + "summary": "Tells listeners the current status of a player", + "params": [ + { + "name": "playerId", + "summary": "The id of the player the status is for", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "status", + "summary": "The status", + "schema": { + "$ref": "#/components/schemas/PlayerStatus" + }, + "required": true + } + ], + "result": { + "name": "providedResponse", + "schema": { + "const": null + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "playerId", + "value": "123" + }, + { + "name": "status", + "value": { + "mediaSessionId": "sess2", + "state": "BLOCKED", + "blockedReason": "CONTENT_NOT_FOUND" + } + } + ], + "result": { + "name": "providedResponse", + "value": null + } + } + ] + }, + { + "name": "provideProgress", + "tags": [ + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:base" + } + ], + "summary": "Tells listeners the current progress of a player", + "params": [ + { + "name": "playerId", + "summary": "The id of the player the progress is for", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "progress", + "summary": "The progress", + "schema": { + "$ref": "#/components/schemas/PlayerProgress" + }, + "required": true + } + ], + "result": { + "name": "providedResponse", + "schema": { + "const": null + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "playerId", + "value": "123" + }, + { + "name": "progress", + "value": { + "speed": 1, + "startPosition": 0, + "position": 5000, + "endPosition": 3600000, + "liveSyncTime": "2021-04-23T18:25:43.511Z" + } + } + ], + "result": { + "name": "providedResponse", + "value": null + } + } + ] + } + ], + "components": { + "schemas": { + "PlayerLoadRequest": { + "title": "PlayerLoadRequest", + "type": "object", + "required": [ + "playerId", + "locator" + ], + "properties": { + "playerId": { + "description": "The id of the player instance to load the locator into", + "type": "string" + }, + "locator": { + "description": "A locator to the content to load", + "type": "string", + "format": "uri" + }, + "metadata": { + "description": "An opaque set of metadata that will be relevant to the player.", + "type": "object" + }, + "autoPlay": { + "description": "Start playing immediately on load without needing to call Player.play", + "type": "boolean" + } + }, + "examples": [ + { + "playerId": "app1:123", + "locator": "https://cdn.rdkcentral.com/media/assets/asset.hls" + }, + { + "playerId": "app2:345", + "locator": "https://cdn.rdkcentral.com/media/assets/asset-2.hls", + "metadata": { + "assetType": "linear" + }, + "autoPlay": true + } + ] + }, + "PlayerMediaSession": { + "title": "PlayerMediaSession", + "type": "object", + "required": [ + "mediaSessionId" + ], + "properties": { + "mediaSessionId": { + "description": "The id of media session that was started, when the content was loaded. This should be a new value on each load", + "type": "string" + } + }, + "examples": [ + { + "mediaSessionId": "sess1" + }, + { + "mediaSessionId": "sess2" + } + ] + }, + "PlayerStatus": { + "title": "PlayerStatus", + "type": "object", + "required": [ + "mediaSessionId", + "state" + ], + "properties": { + "mediaSessionId": { + "description": "The id of media session that is currently loaded", + "type": "string" + }, + "state": { + "description": "The state of the player", + "type": "string", + "enum": [ + "IDLE", + "PENDING", + "PLAYING", + "BLOCKED", + "FAILED" + ] + }, + "blockedReason": { + "description": "The state of the player", + "type": "string", + "enum": [ + "NO_NETWORK", + "CONTENT_NOT_FOUND", + "DRM_ERROR", + "NOT_ENTITLED", + "GEO_BLOCKED", + "CHANNEL_NOT_SCANNED", + "NO_SIGNAL", + "TECHNICAL_FAULT", + "CHANNEL_OFF_AIR", + "PLAYER_FAILURE" + ] + } + }, + "examples": [ + { + "mediaSessionId": "sess1", + "state": "IDLE" + }, + { + "mediaSessionId": "sess2", + "state": "BLOCKED", + "blockedReason": "CONTENT_NOT_FOUND" + } + ] + }, + "PlayerProgress": { + "title": "PlayerProgress", + "type": "object", + "required": [ + "speed", + "startPosition", + "position", + "endPosition", + "liveSyncTime" + ], + "properties": { + "speed": { + "description": "The playback speed as a multiplier", + "type": "number" + }, + "startPosition": { + "description": "The position that the media starts at in milliseconds", + "type": "integer" + }, + "position": { + "description": "The current position in milliseconds", + "type": "integer" + }, + "endPosition": { + "description": "The position that the media stops at in milliseconds", + "type": "integer" + }, + "liveSyncTime": { + "description": "The time to sync to live", + "type": "string", + "format": "date-time" + } + }, + "examples": [ + { + "speed": 1, + "startPosition": 0, + "position": 5000, + "endPosition": 3600000, + "liveSyncTime": "2021-04-23T18:25:43.511Z" + }, + { + "speed": 3, + "startPosition": 5000, + "position": 10000, + "endPosition": 3600000, + "liveSyncTime": "2021-04-23T18:25:43.511Z" + } + ] + }, + "PlayerLoadProviderRequest": { + "title": "PlayerLoadProviderRequest", + "type": "object", + "required": [ + "correlationId", + "parameters" + ], + "properties": { + "correlationId": { + "type": "string", + "description": "An id to correlate the provider response with this request" + }, + "parameters": { + "description": "The request to load media in the player", + "$ref": "#/components/schemas/PlayerLoadRequest" + } + } + } + } + } +} \ No newline at end of file diff --git a/src/openrpc/streaming_player.json b/src/openrpc/streaming_player.json new file mode 100644 index 000000000..c800b22ec --- /dev/null +++ b/src/openrpc/streaming_player.json @@ -0,0 +1,165 @@ +{ + "openrpc": "1.2.4", + "info": { + "title": "StreamingPlayer", + "description": "A module for controlling and accessing media over streaming", + "version": "0.0.0" + }, + "methods": [ + { + "name": "create", + "tags": [ + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:player:streaming" + ] + }, + { + "name": "launch-provider" + } + ], + "summary": "Creates an instance of a player that can be used to play media over streaming. Player instance that is created should also provide firebolt capability 'xrn:firebolt:capability:player:base'. If there is no provider running but there is a provider in the catalog, it will be launched.", + "params": [ + { + "name": "request", + "summary": "The create request", + "schema": { + "$ref": "#/components/schemas/StreamingPlayerCreateRequest" + }, + "required": true + } + ], + "result": { + "name": "playerInstance", + "schema": { + "$ref": "#/components/schemas/StreamingPlayerInstance" + } + }, + "examples": [ + { + "name": "Default example #1", + "params": [ + { + "name": "request", + "value": {} + } + ], + "result": { + "name": "playerInstance", + "value": { + "playerId": "123", + "windowId": "456" + } + } + } + ] + }, + { + "name": "onRequestCreate", + "summary": "Registers as a provider for creating player instances", + "params": [], + "tags": [ + { + "name": "event", + "x-response": { + "$ref": "#/components/schemas/StreamingPlayerInstance", + "examples": [ + { + "playerId": "123", + "windowId": "456" + } + ] + } + }, + { + "name": "capabilities", + "x-provides": "xrn:firebolt:capability:player:streaming", + "x-allow-focus": false + } + ], + "result": { + "name": "createRequest", + "summary": "The request to create a new player", + "schema": { + "$ref": "#/components/schemas/StreamingPlayerCreateProviderRequest" + } + }, + "examples": [ + { + "name": "Default Example", + "params": [], + "result": { + "name": "Default Result", + "value": { + "correlationId": "abc", + "parameters": {} + } + } + } + ] + } + ], + "components": { + "schemas": { + "StreamingPlayerCreateProviderRequest": { + "title": "StreamingPlayerCreateProviderRequest", + "type": "object", + "required": [ + "correlationId", + "parameters" + ], + "properties": { + "correlationId": { + "type": "string", + "description": "An id to correlate the provider response with this request" + }, + "parameters": { + "description": "The request to load media in the player", + "$ref": "#/components/schemas/StreamingPlayerCreateRequest" + } + }, + "examples": [ + {} + ] + }, + "StreamingPlayerCreateRequest": { + "title": "StreamingPlayerCreateRequest", + "type": "object", + "required": [], + "properties": {}, + "examples": [ + {} + ] + }, + "StreamingPlayerInstance": { + "title": "StreamingPlayerInstance", + "type": "object", + "required": [ + "playerId", + "windowId" + ], + "properties": { + "playerId": { + "description": "The id of player which can be used to load media or control the player", + "type": "string" + }, + "windowId": { + "description": "The id of window which will render the media in, can be used to control on screen where the media is shown", + "type": "string" + } + }, + "examples": [ + { + "playerId": "123", + "windowId": "456" + }, + { + "playerId": "abc", + "windowId": "def" + } + ] + } + } + } +} \ No newline at end of file diff --git a/src/schemas/player.json b/src/schemas/player.json new file mode 100644 index 000000000..0af4247ea --- /dev/null +++ b/src/schemas/player.json @@ -0,0 +1,45 @@ +{ + "$id": "https://meta.comcast.com/firebolt/player", + "title": "Player", + "definitions": { + "PlayerRequest": { + "title": "PlayerRequest", + "type": "object", + "required": [ + "playerId" + ], + "properties": { + "playerId": { + "description": "The id of the player instance to play in", + "type": "string" + } + }, + "examples": [ + { + "playerId": "app1:123" + }, + { + "playerId": "app2:345" + } + ] + }, + "PlayerProviderRequest": { + "title": "PlayerProviderRequest", + "type": "object", + "required": [ + "correlationId", + "parameters" + ], + "properties": { + "correlationId": { + "type": "string", + "description": "An id to correlate the provider response with this request" + }, + "parameters": { + "description": "The player request", + "$ref": "#/definitions/PlayerRequest" + } + } + } + } +} \ No newline at end of file diff --git a/src/sdks/manage/sdk.config.json b/src/sdks/manage/sdk.config.json index 56d869412..0b78b215f 100644 --- a/src/sdks/manage/sdk.config.json +++ b/src/sdks/manage/sdk.config.json @@ -141,6 +141,24 @@ "manage": [ "xrn:firebolt:capability:discovery:sign-in-status" ] + }, + { + "module": "Player", + "use": [ + "xrn:firebolt:capability:player:base" + ] + }, + { + "module": "BroadcastPlayer", + "use": [ + "xrn:firebolt:capability:player:broadcast" + ] + }, + { + "module": "StreamingPlayer", + "use": [ + "xrn:firebolt:capability:player:streaming" + ] } ] -} +} \ No newline at end of file diff --git a/src/sdks/provider/.npmignore b/src/sdks/provider/.npmignore new file mode 100644 index 000000000..0e2ba4d22 --- /dev/null +++ b/src/sdks/provider/.npmignore @@ -0,0 +1,6 @@ +build/* +src/* +test/* +.DS_Store +jest.config.* +tsconfig.* \ No newline at end of file diff --git a/src/sdks/provider/CHANGELOG.md b/src/sdks/provider/CHANGELOG.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/sdks/provider/CONTRIBUTING.md b/src/sdks/provider/CONTRIBUTING.md new file mode 120000 index 000000000..c97564d93 --- /dev/null +++ b/src/sdks/provider/CONTRIBUTING.md @@ -0,0 +1 @@ +../../../CONTRIBUTING.md \ No newline at end of file diff --git a/src/sdks/provider/LICENSE b/src/sdks/provider/LICENSE new file mode 120000 index 000000000..5853aaea5 --- /dev/null +++ b/src/sdks/provider/LICENSE @@ -0,0 +1 @@ +../../../LICENSE \ No newline at end of file diff --git a/src/sdks/provider/NOTICE b/src/sdks/provider/NOTICE new file mode 120000 index 000000000..295f6bdb3 --- /dev/null +++ b/src/sdks/provider/NOTICE @@ -0,0 +1 @@ +../../../NOTICE \ No newline at end of file diff --git a/src/sdks/provider/README.md b/src/sdks/provider/README.md new file mode 100644 index 000000000..04710aaff --- /dev/null +++ b/src/sdks/provider/README.md @@ -0,0 +1,26 @@ +--- +title: Firebolt Provider SDK +--- + +[![semantic-release: conventional](https://img.shields.io/badge/semantic--release-conventional-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release) + +# Firebolt Provider SDK +For building Firebolt compliant apps that manage Firebolt devices. + +## Usage +To install, run: + +``` +npm install @firebolt-js/provider-sdk +``` + +To use the package, import one of it's modules, e.g.: + +```js +import { Privacy } from '@firebolt-js/provider-sdk' +``` + +## Contributing +The Firebolt SDKs are built using the Firebolt OpenRPC toolset: + +See [Firebolt OpenRPC](https://www.github.com/rdkcentral/firebolt-openrpc/), for more info. diff --git a/src/sdks/provider/Setup.js b/src/sdks/provider/Setup.js new file mode 100644 index 000000000..472edc35c --- /dev/null +++ b/src/sdks/provider/Setup.js @@ -0,0 +1,36 @@ +if (!window.__firebolt) { + window.__firebolt = {} +} + +// wires up the mock transport w/out waiting +window.__firebolt.mockTransportLayer = true + +// sets a flag that mock defaults impls can use to speed things up, e.g. Lifecycle/defaults.js +window.__firebolt.automation = true + +let sendListener +let receiver + +export const transport = { + send: function(message) { + const json = JSON.parse(message) + sendListener && sendListener(json) + }, + receive: function(callback) { + // store the callback + receiver = callback + }, + onSend: function(listener) { + sendListener = listener + }, + response: function(id, result) { + let response = { + jsonrpc: '2.0', + id: id, + result: result + } + receiver && receiver(JSON.stringify(response)) + } +} + +window.__firebolt.setTransportLayer(transport) \ No newline at end of file diff --git a/src/sdks/provider/jest.config.json b/src/sdks/provider/jest.config.json new file mode 100644 index 000000000..745370cfa --- /dev/null +++ b/src/sdks/provider/jest.config.json @@ -0,0 +1,8 @@ +{ + "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|js?)$", + "transform": {}, + "testPathIgnorePatterns": ["/node_modules/", "/../../../test"], + "moduleFileExtensions": ["js", "jsx", "mjs"], + "verbose": true, + "testEnvironment": "jest-environment-jsdom" + } \ No newline at end of file diff --git a/src/sdks/provider/package.json b/src/sdks/provider/package.json new file mode 100644 index 000000000..57cd83127 --- /dev/null +++ b/src/sdks/provider/package.json @@ -0,0 +1,51 @@ +{ + "name": "@firebolt-js/provider-sdk", + "version": "0.16.0-next.3", + "description": "The Firebolt Provider JS SDK", + "main": "./dist/lib/firebolt-provider.mjs", + "types": "./dist/lib/firebolt-provider.d.ts", + "exports": { + ".": "./dist/lib/firebolt-provider.mjs" + }, + "type": "module", + "scripts": { + "validate": "npx firebolt-openrpc validate --input ./dist/firebolt-provider-open-rpc.json", + "sdk": "npx firebolt-openrpc sdk --input ./dist/firebolt-provider-open-rpc.json --template ./src/js --output ./build/javascript/src", + "native": "npx firebolt-openrpc sdk --input ./dist/firebolt-provider-open-rpc.json --template ./src/js --output ./build/c/src --language ../../../node_modules/@firebolt-js/openrpc/languages/c", + "compile": "cd ../../.. && npm run compile", + "slice": "npx firebolt-openrpc slice -i ../../../dist/firebolt-open-rpc.json --sdk ./sdk.config.json -o ./dist/firebolt-provider-open-rpc.json", + "docs": "npx firebolt-openrpc docs --input ./dist/firebolt-provider-open-rpc.json --output build/docs/markdown --as-path", + "wiki": "npx firebolt-openrpc docs --input ./dist/firebolt-provider-open-rpc.json --output build/docs/markdown", + "dist:notest": "npm run clean && npm run slice && npm run validate && npm run sdk && npm run docs && npm run dist:copy && echo 'Firebolt Provider SDK /dist/ is ready.\n'", + "dist:copy": "npm run dist:copy:sdk && npm run dist:copy:docs", + "dist:copy:sdk": "mkdirp ./dist && cp -R build/javascript/src dist/lib && cp ./dist/firebolt-provider-open-rpc.json ../../../dist/firebolt-provider-open-rpc.json", + "dist:copy:docs": "mkdirp ./dist && cp -R build/docs/markdown dist/docs", + "dist": "npm run dist:notest && npm run test", + "clean": "rm -rf ./build && rm -rf ./dist", + "test:setup": "rm -rf test/transpiled-suite && npx tsc --target es6 --moduleResolution node --outDir test/transpiled-suite", + "test": "npm run test:setup && NODE_OPTIONS=--experimental-vm-modules npx --config=jest.config.json --detectOpenHandles jest", + "prepack": "node ../../js/version.mjs validate && npm run broilerplate", + "broilerplate": "rm ./CONTRIBUTING.md && cp ../../../CONTRIBUTING.md ./CONTRIBUTING.md && rm ./LICENSE && cp ../../../LICENSE ./LICENSE && rm ./NOTICE && cp ../../../NOTICE ./NOTICE" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/rdkcentral/firebolt-core-sdk", + "directory": "src/sdks/provider" + }, + "author": "", + "bugs": { + "url": "https://github.com/rdkcentral/firebolt-core-sdk/issues" + }, + "homepage": "https://github.com/rdkcentral/firebolt-core-sdk#readme", + "devDependencies": { + "jest": "^28.1.0", + "jest-environment-jsdom": "^28.1.3", + "typescript": "^4.6.4" + }, + "keywords": [ + "firebolt", + "apps", + "sdk" + ], + "license": "Apache-2.0" +} \ No newline at end of file diff --git a/src/sdks/provider/sdk.config.json b/src/sdks/provider/sdk.config.json new file mode 100644 index 000000000..47da2f577 --- /dev/null +++ b/src/sdks/provider/sdk.config.json @@ -0,0 +1,26 @@ +{ + "info": { + "title": "Firebolt Provider SDK", + "x-interface-names": {} + }, + "methods": [ + { + "module": "Player", + "provide": [ + "xrn:firebolt:capability:player:base" + ] + }, + { + "module": "BroadcastPlayer", + "provide": [ + "xrn:firebolt:capability:player:broadcast" + ] + }, + { + "module": "StreamingPlayer", + "provide": [ + "xrn:firebolt:capability:player:streaming" + ] + } + ] +} \ No newline at end of file diff --git a/src/sdks/provider/src/js/sdk/index.mjs b/src/sdks/provider/src/js/sdk/index.mjs new file mode 100644 index 000000000..a9f2f5ca6 --- /dev/null +++ b/src/sdks/provider/src/js/sdk/index.mjs @@ -0,0 +1,30 @@ +/* + * Copyright 2021 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { setMockResponses } from './Transport/MockTransport.mjs' + +/* ${MOCK_IMPORTS} */ + +setMockResponses({ + /* ${MOCK_OBJECTS} */ +}) + +/* ${EXPORTS} */ +export { default as Log } from './Log/index.mjs' +export { default as Events } from './Events/index.mjs' +export { default as Settings } from './Settings/index.mjs' diff --git a/src/sdks/provider/test/suite/player.test.ts b/src/sdks/provider/test/suite/player.test.ts new file mode 100644 index 000000000..401c11b8b --- /dev/null +++ b/src/sdks/provider/test/suite/player.test.ts @@ -0,0 +1,39 @@ +/* + * Copyright 2021 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { test, expect } from '@jest/globals' +import { Player } from '../../build/javascript/src/firebolt-provider' + +test('Player.provideStatus()', async () => { + const resp = await Player.provideStatus('abc', { + mediaSessionId: '123', + state: 'PLAYING' + }) + expect(resp).toEqual(null) +}) + +test('Player.provideProgress', async () => { + const resp = await Player.provideProgress('abc', { + startPosition: 0, + position: 60000, + endPosition: 3600000, + liveSyncTime: '2021-04-23T18:25:43.511Z', + speed: 1 + }) + expect(resp).toEqual(null) +}) diff --git a/src/sdks/provider/tsconfig.json b/src/sdks/provider/tsconfig.json new file mode 100644 index 000000000..56ff58bc8 --- /dev/null +++ b/src/sdks/provider/tsconfig.json @@ -0,0 +1,5 @@ +{ + "include": [ + "test/suite/*" + ] +} \ No newline at end of file