Skip to main content
All UI components are SceneGraph nodes that run on the render thread. Each screen implements ApplyResponsiveLayout() so MainScene can relayout it when the display resolution changes.
File: components/MainScene.*
Extends: Scene

Purpose

Root scene and app lifecycle orchestrator. Initializes global state, manages the screen stack, drives the handshake → auth → playlist startup sequence, and handles deep links.

Interface fields

<field id="launchDeepLink"  type="assocarray" onChange="onLaunchDeepLink" />
<field id="inputDeepLink"   type="assocarray" onChange="onInputDeepLink" />
<field id="exitRequested"   type="integer"    value="0" />
FieldDirectionDescription
launchDeepLinkinputCold-start deep link payload (mediaType, contentId). Set by main.brs.
inputDeepLinkinputWarm-start deep link payload. Set by main.brs on input event.
exitRequestedoutputIncremented when the user confirms exit; observed by main.brs.

Key children

<Rectangle id="bgRect" width="1920" height="1080" color="0x0F1020FF" />

Key behaviors

  • On init(): calls GTV_InitGlobalState(), creates relayout and focus-repair timers, creates the session auth timer (SESSION_AUTH_CHECK_MS = 420000 ms), then calls ShowSplash().
  • After splash: checks registry for saved credentials. If found, runs auto-login; otherwise shows OnboardingScreen.
  • Screen stack: only one primary screen is active at a time (m.currentScreen). MainScreen and PlayerScreen co-exist as siblings; MainScreen is shown in overlay mode when the channel list is requested over the player.
  • Session auth timer fires every 7 minutes while authenticated and re-runs AuthTask silently. On failure it classifies the reason and shows the appropriate session-issue dialog.
  • Signals AppDialogInitiate / AppDialogComplete Roku certification beacons during pre-home dialogs.
  • signalBeacon("AppLaunchComplete") is fired by MainScreen once the channel grid is visible.
File: components/SplashScreen/SplashScreen.*
Extends: Group

Purpose

Launch splash displayed immediately after app start. Shows the GlobalTV logo and splash image, then fires splashDone after SPLASH_MS (1 500 ms).

Interface fields

<field id="splashDone" type="boolean" value="false" />
<function name="ApplyResponsiveLayout" />
FieldDirectionDescription
splashDoneoutputSet to true when the timer fires; observed by MainScene.OnSplashDone.

Key children

<Rectangle  id="bg"         color="0x1A1A2EFF" />
<Poster     id="splashImg"  uri="pkg:/images/splash_hd.png" />
<Poster     id="logoImg"    uri="pkg:/images/globaltv-logo.png" visible="false" />
<Label      id="versionLabel" />
<Timer      id="splashTimer" duration="1.5" repeat="false" />

Key behaviors

  • Timer duration maps directly to AppConstants().SPLASH_MS / 1000 (1.5 seconds).
  • ApplyResponsiveLayout() repositions children to match the current safe-area layout context.
File: components/OnboardingScreen/OnboardingScreen.*
Extends: Group

Purpose

First-run / logged-out screen. Presents the app branding and a prompt to proceed to login. Also handles exit requests.

Interface fields

<field id="goToLogin"    type="boolean" value="false" />
<field id="requestExit"  type="integer" value="0" />
FieldDirectionDescription
goToLoginoutputSet to true when the user presses the login button. Observed by MainScene.OnGoToLogin.
requestExitoutputIncremented when the user presses Back to exit. Observed by MainScene.OnRequestExit.

Key behaviors

  • Signals AppDialogInitiate("OnboardingScreen") for Roku certification timing.
  • ApplyResponsiveLayout() adapts to 1080p / 720p display modes.
File: components/LoginScreen/LoginScreen.*
Extends: Group

Purpose

On-device credential entry screen. Collects username and password, optionally calls Roku’s getUserData RFI to pre-fill the Roku account email, authenticates via AuthTask, and returns the result to MainScene.

Interface fields

<field id="loginSucceeded" type="boolean"   value="false" />
<field id="loginResult"    type="assocarray" />
<function name="ApplyResponsiveLayout" />
FieldDirectionDescription
loginSucceededoutputSet to true on successful auth. Observed by MainScene.OnLoginSucceeded.
loginResultoutputAssocArray with username, password, and optional rokuEmail.

Key children

<Poster     id="loginBg"    uri="pkg:/images/login_bg_fhd.png" />
<Label      id="usernameValue" />
<Label      id="passwordValue" />
<Label      id="lblError"   visible="false" />
<Label      id="statusHintLabel" visible="false" />
<GTV_Spinner id="spinner"  visible="false" />

Key behaviors

  • Two virtual keyboard fields (username, password) managed on the render thread via standard roKeyEvent handling.
  • “Show password” toggle reveals masked password characters.
  • Calls Roku getUserData to request the subscriber’s Roku email (rokuEmail) as part of the auth context.
  • Displays inline statusHintLabel during auth to relay AuthTask.statusMessage progress text (e.g. “Conectando con servidor local…”).
  • Signals AppDialogInitiate("LoginScreen") for certification beacon tracking.
File: components/MainScreen/MainScreen.*
Extends: Group

Purpose

Channel grid/list. Displays channels organized by category rows. Operates in two modes: full-screen (normal navigation) and overlay mode (transparent panel over the active player).

Interface fields

<field id="channels"         type="array"   onChange="onChannelsChanged" />
<field id="categories"       type="array" />
<field id="initialIndex"     type="integer" value="0" />
<field id="channelSelected"  type="integer" value="-1" />
<field id="openSettings"     type="boolean" value="false" />
<field id="overlayMode"      type="boolean" value="false" onChange="onOverlayModeChanged" />
<field id="closeOverlay"     type="integer" value="0" />
<field id="requestExit"      type="integer" value="0" />
<field id="infoMessage"      type="string"  value="" onChange="onInfoMessageChanged" />
<function name="GiveFocusToRowList" />
<function name="ReleaseOverlayFocus" />
<function name="ApplyResponsiveLayout" />
<function name="SyncFocusToFlatIndex" />
<function name="RestoreOverlayContext" />
<function name="HandleOverlayKey" />
FieldDirectionDescription
channelsinputFlat array of channel objects from the playlist parser.
categoriesinputArray of category name strings.
initialIndexinputFlat channel index to pre-select on load.
channelSelectedoutputFlat index of the channel the user activated.
openSettingsoutputSet to true when the user opens Settings from within the grid.
overlayModeinputtrue = transparent panel over player; false = full-screen.
closeOverlayoutputIncremented when the user dismisses the overlay (Back key).
requestExitoutputIncremented when the user requests exit from the grid.
infoMessageinputShort status string shown in a banner (e.g. “Lista actualizada.”).

Key behaviors

  • Fires signalBeacon("AppLaunchComplete") the first time the grid becomes visible, satisfying the Roku certification requirement.
  • In overlay mode the background is set to COLOR_OVERLAY (0x000000CC) so the live video below remains visible.
  • SyncFocusToFlatIndex({flatIndex, forceTodos}) scrolls the row list to the channel matching the currently playing index.
  • RestoreOverlayContext({categoryIndex, rowIndex}) restores the last manually selected row when reopening the overlay.
File: components/PlayerScreen/PlayerScreen.*
Extends: Group

Purpose

Live stream player. Hosts the Video node, manages channel switching, reconnection, freeze detection, ad viewport reduction, and all player-level dialogs (offline, inactive, error).

Interface fields

<field id="channelIndex"   type="integer" value="-1" onChange="onChannelIndexChanged" />
<field id="requestOverlay" type="integer" value="0" />
<field id="closeOverlay"   type="integer" value="0" />
<field id="exitPlayer"     type="boolean" value="false" />
<field id="openSettings"   type="boolean" value="false" />
<field id="userInactive"   type="boolean" value="false" />
<field id="requestExit"    type="integer" value="0" />
<field id="modalActive"    type="boolean" value="false" />
<function name="ApplyResponsiveLayout" />
<function name="FocusActiveModal" />
<function name="FocusPlaybackNode" />
<function name="IsAnyModalOpen" />
<function name="IsOfflineModalOpen" />
FieldDirectionDescription
channelIndexinputFlat index into m.global.channelList. Setting this tunes to the channel.
requestOverlayoutputIncremented when the user presses Up/OK to show the channel list overlay.
closeOverlayoutputIncremented when the user closes the overlay from within the player.
exitPlayeroutputSet to true when the user backs out of the player entirely.
openSettingsoutputSet to true when the user opens the Settings overlay from the player.
userInactiveoutputSet to true when AdsPollingTask signals account inactivity.
modalActiveoutputtrue while any player-level modal dialog (error, offline, inactive) is open.

Key behaviors

  • Starts AdsPollingTask and ConnectivityTask as soon as a channel is loaded.
  • AdManager is embedded and observes adData / adsSnapshot from the polling task.
  • When AdFormatC is active, videoHeightReduction and videoOffsetY fields shrink the Video node’s viewport to make room for the bottom-banner ad.
  • Freeze detection timer (FREEZE_CHECK_MS = 10 000 ms) restarts the stream automatically if no position change is detected.
  • Network recovery: when ConnectivityTask reports internet restored after an outage, the player attempts a reconnect.
  • StopVideo() is called by MainScene before session resets and server changes.
File: components/SettingsScreen/SettingsScreen.*
Extends: Group

Purpose

Configuration panel. Provides channel refresh, logout, safe-area adjustment, and a technical server management panel.

Interface fields

<field id="closeSettings"              type="boolean" value="false" />
<field id="logoutRequested"            type="boolean" value="false" />
<field id="refreshChannelsRequested"   type="integer" value="0" />
<field id="safeAreaChanged"            type="integer" value="0" />
<field id="applyServerRequested"       type="boolean" value="false" />
<field id="applyServerId"              type="string"  value="" />
<function name="ApplyResponsiveLayout" />
FieldDirectionDescription
closeSettingsoutputSet to true when the user exits Settings.
logoutRequestedoutputSet to true when the user confirms logout.
refreshChannelsRequestedoutputIncremented each time the user triggers a channel list refresh.
safeAreaChangedoutputIncremented when the user adjusts the safe-area margin; observed by MainScene to trigger layout relayout.
applyServerRequestedoutputSet to true when the user selects a server to apply. applyServerId carries the profile ID.

Key behaviors

  • Server panel shows profiles loaded from GTV_LoadServerProfiles(). Each profile can be probed via ServerProbeTask.
  • Safe-area margin persists to registry via GTV_RegSaveSafeMarginPct() and triggers OnSettingsSafeAreaChanged in MainScene, which calls ApplySceneLayout() and relayouts all active screens.
  • Logout clears saved credentials and cache via GTV_RegClearCredentials() / GTV_RegClearCache().
File: components/ads/AdManager.*
Extends: Group

Purpose

Ad lifecycle manager. Receives ad payloads from AdsPollingTask, instantiates the correct format renderer (AdFormatA, AdFormatB, or AdFormatC), manages viewport reduction for format C, and emits metric events.

Interface fields

<field id="adPayload"            type="assocarray" onChange="onAdPayload" />
<field id="adsSnapshot"          type="assocarray" onChange="onAdsSnapshot" />
<field id="clearAds"             type="boolean"    value="false" onChange="onClearAds" />
<field id="trackMetric"          type="assocarray" />
<field id="allAdsHidden"         type="boolean"    value="false" />
<field id="videoHeightReduction" type="integer"    value="0" />
<field id="videoOffsetY"         type="integer"    value="0" />
<field id="videoViewport"        type="assocarray" onChange="onVideoViewportChanged" />
<field id="videoBaseViewport"    type="assocarray" onChange="onVideoBaseViewportChanged" />
FieldDirectionDescription
adPayloadinputSingle normalized ad object from AdsPollingTask.adData.
adsSnapshotinputFull snapshot object from AdsPollingTask.adsSnapshot.
clearAdsinputSet to true to tear down all active ad renderers.
trackMetricoutputAssocArray metric event written here for MetricsTask to consume.
allAdsHiddenoutputtrue when no ad is currently visible.
videoHeightReductionoutputPixels to shrink the Video node height (Format C only).
videoOffsetYoutputY offset for the Video node when Format C is active.
videoViewportinputCurrent video viewport dimensions; used to position format renderers.
videoBaseViewportinputUnmodified base viewport; used to restore after Format C teardown.

Key behaviors

  • Inspects adPayload.format.type to select AdFormatA, AdFormatB, or AdFormatC.
  • Tracks impression start time; on teardown emits an ad_impression_closed metric with visible_ms.
Files: components/ads/AdFormatA.*, AdFormatB.*, AdFormatC.*
Extends: Group

Purpose

Individual ad format renderers. Each loads a remote media URL into a Poster node and fades it in. Format C additionally reports viewport reduction values so PlayerScreen can shrink the live video to make room.

Interface fields (all three formats)

<field id="adConfig"             type="assocarray" onChange="onAdConfigChanged" />
<field id="imageLoaded"          type="boolean"    value="false" />
<field id="imageError"           type="boolean"    value="false" />

Additional fields — AdFormatC only

<field id="videoHeightReduction" type="integer" value="0" />
<field id="videoOffsetY"         type="integer" value="0" />
FieldDescription
adConfigNormalized ad payload from AdManager. Contains media_url, format, ad_id, etc.
imageLoadedSet to true when the Poster has finished loading.
imageErrorSet to true if the image load fails.
videoHeightReduction (C only)Pixels to reduce the player’s video height.
videoOffsetY (C only)Y offset to apply to the video node.

Key children (all three)

<Poster id="adPoster" loadDisplayMode="scaleToFit" visible="false" />
<Timer  id="fadeTimer" duration="0.05" repeat="true" />

Key behaviors

  • Format A — Full-screen or large overlay image, fades in over the video.
  • Format B — Partial overlay image at a configurable position and size, fades in.
  • Format C — Bottom-banner image. On load, writes videoHeightReduction and videoOffsetY so PlayerScreen pushes the video up to avoid overlap.
  • All formats fade in using a 50 ms repeating timer and fade out on teardown.
Files: components/overlays/NumberOverlay.*, components/overlays/ChannelBanner.*
Extends: Group

NumberOverlay

Displays a channel-number input prompt when the user types digits on the remote. Commits after a 2-second idle timer.
<field id="numberCommitted" type="string" value="" />
FieldDescription
numberCommittedThe full digit string after the commit timer fires; consumed by PlayerScreen to tune to that channel number.
Key children:
<Rectangle id="numBg"     color="0x101B42DD" width="300" height="180" />
<Rectangle id="numAccent" color="0x2D57C1FF" width="6"   height="180" />
<Label     id="lblDigits" font="font:LargeBoldSystemFont" />
<Timer     id="commitTimer" duration="2" repeat="false" />

ChannelBanner

Info overlay shown briefly when a channel starts or changes. Displays channel number, logo, name, live status, and category.
<field id="channelData"    type="assocarray" onChange="onChannelDataChanged" />
<field id="networkOnline"  type="boolean"    value="true" onChange="onNetworkOnlineChanged" />
<field id="statusText"     type="string"     value=""     onChange="onStatusTextChanged" />
FieldDescription
channelDataAssocArray with name, number, logo, group from the parsed channel list.
networkOnlineWhen false, replaces the “En vivo” status with an offline indicator.
statusTextOverride status string (e.g. reconnecting message).
Key children:
<Rectangle id="bannerBg"     color="0x14234FCC" />
<Rectangle id="bannerAccent" color="0x2D57C1FF" />
<Label     id="lblNumber" />
<Poster    id="chLogo" />
<Label     id="lblName" />
<Label     id="lblStatus"   text="En vivo" />
<Label     id="lblCategory" />
<Timer     id="hideTimer"  duration="3"    repeat="false" />
<Timer     id="fadeTimer"  duration="0.05" repeat="true" />
The banner auto-hides after BANNER_MS (3 000 ms) with a fade-out driven by the fadeTimer.