Skip to main content
GlobalTV Roku is a native Roku SceneGraph (RSG) channel written in BrightScript. The application is split into two physical layers — pure BrightScript logic under source/ and SceneGraph XML+BRS components under components/ — that communicate through the RSG scene tree and shared global state.

Roku SceneGraph fundamentals

Roku SceneGraph is a declarative UI framework built on a node tree. Every visual element and background task is a node. Key system concepts used by this app:
  • Scene treeMainScene extends the built-in Scene node and is the root of the entire tree. All screens and tasks are children of MainScene.
  • roSGScreen — the Roku system object that renders the SceneGraph. Created in main.brs, it owns a single MainScene.
  • roMessagePort — the event loop in main.brs. The while true loop waits on this port to receive roSGScreenEvent, roSGNodeEvent, roInputEvent, and roDeviceInfoEvent messages.
  • Tasks — SceneGraph Task nodes run BrightScript on a background thread. They expose observable fields so the scene thread can react to results without blocking the UI.
  • observeField / onChange — the wiring mechanism. When a field value changes, RSG calls the registered handler on the same thread as the observer.
  • m.global — a globally shared roSGNode accessible from every component and task in the app. AppState.brs initialises all fields on it at startup.

Source layer (source/)

Code under source/ runs on the render thread inside MainScene. It is loaded via <script> tags in MainScene.xml.
FileRole
main.brsEntry point. Creates roSGScreen, instantiates MainScene, detects deep links, runs the event loop, and monitors device memory.
AppConstants.brsSingle source of truth for all configuration: server URLs, API paths, timeouts, registry keys, UI constants, colour palette, and auth reason codes.
AppState.brsGTV_InitGlobalState() — adds every m.global field with its default value. Also contains layout helpers (GTV_GetLayoutContext, GTV_GetSafeArea) and auth signal classification (GTV_AuthClassifyFailure).
utils/Logger.brsGTV_Log() (dev only), GTV_Warn(), GTV_Error() — tagged log functions.
utils/HttpClient.brsSynchronous HTTP wrapper for use inside Task nodes.
utils/RegistryManager.brsRead/write helpers for the Roku persistent registry (roRegistrySection). Stores credentials, last server URL, last channel index, safe-margin percentage, and server profiles.
utils/ServerManager.brsServer profile CRUD, URL normalisation, and health-check probing.
utils/M3UParser.brsParses M3U8 playlist files into channel and category arrays.
utils/HealthCheck.brsHTTP health-check against /health with configurable timeout.
utils/NetworkDetector.brsGTV_IsOnline() — checks the active network interface without making an HTTP request.

Components layer (components/)

Screens

MainScene, SplashScreen, OnboardingScreen, LoginScreen, MainScreen, PlayerScreen, SettingsScreen — the full user-facing UI hierarchy from launch through playback.

Background tasks

HandshakeTask, AuthTask, PlaylistTask, ConnectivityTask, AdsPollingTask, MetricsTask, ServerProbeTask — all network I/O runs off the render thread.

Ad system

AdManager coordinates three format renderers: AdFormatA, AdFormatB, and AdFormatC. Format C reduces the video viewport height. Ad data arrives from AdsPollingTask every 10 seconds.

Overlays

channelBanner shows channel name, number, logo, and live status. numberOverlay handles direct numeric channel entry. Both overlay the live video during playback.

Component responsibilities

ComponentTypeResponsibility
MainSceneScene (root)Global state init, screen orchestration, task lifecycle, deep link routing, session auth checks, exit flow
SplashScreenScreenDisplays the launch splash for SPLASH_MS (1500 ms), then fires splashDone
OnboardingScreenScreenFirst-run welcome screen; routes to LoginScreen via goToLogin
LoginScreenScreenOn-device credential form; requests Roku email via ChannelStore.getUserData; runs AuthTask
MainScreenScreenCategory-tabbed channel grid; signals AppLaunchComplete beacon on first channel load; doubles as the channel-selection overlay during playback
PlayerScreenScreenHLS playback via Video node; hosts AdManager, channel banner, number overlay, error and offline dialogs; spawns ConnectivityTask, AdsPollingTask, and MetricsTask
SettingsScreenScreenSafe-area adjustment, channel refresh, logout, server management (admin-unlocked)
HandshakeTaskTaskDiscovers the active server via health-check across the server list; writes activeServer to m.global
AuthTaskTaskAuthenticates username/password against /auth/{user}/{pass}; returns success or failure with a classified reason code
PlaylistTaskTaskDownloads and parses the M3U8 playlist from /auth/{user}/{pass}/playlist/m3u8/hls; returns channels and categories arrays
ConnectivityTaskTaskPolls internet reachability every NET_RETRY_MS (30 s); updates m.global.hasInternet
AdsPollingTaskTaskPerforms ads handshake, then polls /app/ads/active every ADS_POLL_MS (10 s); signals inactivity and session invalidation
MetricsTaskTaskBatches and POSTs impression events to /api/v1/app/metrics/track
ServerProbeTaskTaskOne-shot health-check for a given server URL; used by the settings server-test action
AdManagerComponentReceives ad snapshots; selects and renders the correct format node; manages video viewport reduction for Format C
AdFormatA/B/CComponentIndividual ad renderers; Format C emits videoHeightReduction and videoOffsetY to compress the video area

Utility layer

All utilities are pure BrightScript functions loaded as <script> includes into MainScene.xml. They carry no node state and can be called from any script that shares the same component scope.
' Logger — three severity levels
GTV_Log("MainScene", "init")       ' dev build only
GTV_Warn("PlayerScreen", "No net") ' always printed
GTV_Error("AuthTask", "401")       ' always printed

' HttpClient — synchronous request inside a Task
res = GTV_HttpGet(url, headers, timeoutMs)

' RegistryManager — persistent storage
creds = GTV_RegLoadCredentials()   ' returns { username, password } or invalid
GTV_RegSaveCredentials(user, pass)
GTV_RegSaveLastServer(url)

' Layout helpers — resolution-aware scaling
ctx = GTV_GetLayoutContext(m.top)  ' returns safeX, safeY, safeW, safeH, sx, sy
x   = GTV_LX(ctx, 122)            ' design-space x → screen pixels

Design resolution and safe area

GTV_GetDesignSize() detects the display mode (roDeviceInfo.GetDisplayMode()) and returns 1920×1080 or 1280×720. GTV_GetSafeArea() applies the uiSafeMarginPct registry value (0–10 %) to compute inset bounds. All screens call ApplyResponsiveLayout() on init and whenever currentDesignResolution changes, keeping the layout consistent across FHD and HD Roku models.