The Roku side of PC Caster is a minimal BrightScript SceneGraph channel that does one thing — play any video URL it receives from the PC via the Roku External Control Protocol (ECP). The channel is sideloaded automatically by the app on first cast, lives in theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/iluisgm/PC_Caster/llms.txt
Use this file to discover all available pages before exploring further.
roku_receiver/ directory, and is driven entirely from Python without any user interaction on the TV.
Channel manifest
roku_receiver/manifest
#0d1117). Standard and HD icon variants are included so the channel displays correctly on older Roku models.
Entry point: main.brs
main.brs is the application entry point. It creates the roSGScreen, shows it, and sets up two communication channels: the launchArgs field (populated from the ECP /launch deep-link parameters) and an roInput object (which receives subsequent /input messages while the channel is already running).
roku_receiver/source/main.brs
| Event type | Handling |
|---|---|
roSGScreenEvent.isScreenClosed() | The user pressed the Back/Home button — exits immediately. |
roInputEvent.isInput() | New URL pushed from the PC via POST /input — passed to the scene via the ecpInput field. |
Scene logic: MainScene.brs
init()
Locates the video (roSGNode of type Video) and status (Label) nodes defined in the SceneGraph XML, observes the video’s state field, and sets focus on the video node so remote control events are forwarded to it.
roku_receiver/components/MainScene.brs
onLaunchArgs() / onEcpInput()
Field observers that fire when main.brs writes to launchArgs or ecpInput. Both delegate directly to playFromArgs().
playFromArgs(args)
Reads the URL and format from the argument associative array. The URL is checked under three different key names in priority order, for compatibility with different ECP callers:
roku_receiver/components/MainScene.brs
mediaType → videoFormat → "hls".
playUrl(url, fmt)
Creates a ContentNode, sets its url, streamFormat, and title, assigns it to m.video.content, and starts playback with m.video.control = "play".
roku_receiver/components/MainScene.brs
onVideoState()
Observes the video state field and manages the status label:
| State | Behaviour |
|---|---|
"playing" | Hides the status label. |
"error" | Shows "Playback error — check the proxy is running on the PC." |
| Any other | Shows "Status: <state>" (e.g. "buffering", "paused"). |
ECP control from Python
roku_deploy.py exposes three functions for driving the channel from Python.
Sideloading
roku_deploy.py
build_zip() walks roku_receiver/ and packs every file into a ZIP archive with manifest at the root (the Roku installer requires this). sideload() POSTs the archive to the Roku developer web server using HTTP Digest authentication — HTTPDigestAuth('rokudev', password) from requests.auth:
Launching and updating
roku_deploy.py
launch() starts the channel from scratch (or restarts it if it was on a different screen). input_play() pushes a new URL to the channel while it’s already running — the channel switches to the new stream without any visible interruption to the Roku home screen.
Checking installation
roku_deploy.py
is_installed() queries the ECP /query/apps endpoint and scans the XML for id="dev". If the channel is absent, the main app calls sideload() automatically before the next launch().
Sideloaded channels always have the app ID
dev. This means only one sideloaded channel can exist at a time on a Roku — installing PC Caster will replace any other sideloaded channel you had previously.