Startup and navigation flow
main.brs — channel entry point
Roku calls If
Main(args) in source/main.brs. The function creates the screen stack objects, instantiates MainScene, and enters the main event loop.args contains a valid mediaType=live deep link, it is forwarded to scene.launchDeepLink before the event loop starts.MainScene.init() — global state and splash
MainScene.init() runs on the render thread immediately after the scene is created:- Calls
GTV_InitGlobalState()to populate allm.globalfields. - Sets up layout timers, focus-repair timer, and the periodic session-auth timer.
- Calls
ShowSplash()to create and displaySplashScreen.
SplashScreen — branding display
SplashScreen plays the splash animation for SPLASH_MS (1 500 ms by default) then fires the splashDone field.MainScene observes splashDone and calls OnSplashDone().Credential check — auto-login or onboarding
OnSplashDone() calls GTV_RegLoadCredentials() to read saved credentials from the Roku registry.- Credentials found →
RunAutoLogin()(step 5) - No credentials →
ShowOnboarding()(step 6)
Auto-login path — AuthTask
RunAutoLogin() creates an AuthTask node, passes the saved credentials, and waits for done.OnAuthDone() calls OnAuthSuccess() which starts a PlaylistTask (step 7). On failure, the reason code is classified and the appropriate error UI is shown (session issue dialog, credentials dialog, or offline dialog).Onboarding path — manual login
When no saved credentials exist,
ShowOnboarding() creates OnboardingScreen. The user presses a button to proceed to LoginScreen.LoginScreen captures username and password, optionally requests the Roku account email via getUserData, and authenticates against the backend. On success, credentials are saved to the registry and OnAuthSuccess() is called.PlaylistTask — channel catalog
OnAuthSuccess() calls RunPlaylistTask("startup") which creates a PlaylistTask node. The task downloads and parses the M3U8 playlist, building channelList and categories.OnPlaylistDone() is called.PlayerScreen — live video starts
OnPlaylistDone() resolves the startup channel index (considering any pending deep link) and calls ShowPlayer(startIdx).ShowPlayer() also creates MainScreen in the background if it does not already exist, inserting it below PlayerScreen in the scene tree so the overlay is ready immediately.MainScreen dispatches the AppLaunchComplete beacon once it has rendered.Overlay and settings
From the player, the user can:
- Press the remote’s Up or OK to request the channel overlay (
OnRequestOverlay()), makingMainScreenvisible in overlay mode on top of the player. - Navigate to a different channel in the overlay, which sets
m.playerScreen.channelIndexon the existing player node. - Open
SettingsScreenfrom eitherMainScreenorPlayerScreenvia theopenSettingsfield. - Trigger
OnLogoutRequested()from settings, which clears credentials and returns toLoginScreen.
Deep-link handling
GlobalTV supports one deep-link media type:mediaType=live with a contentId matching a channel ID in the playlist.
Cold-start deep link (launch event)
When the channel is launched directly into a deep link, Roku passesargs to Main(). The helper GTV_IsLiveDeepLink() validates the payload:
main.brs sets scene.launchDeepLink = args, which triggers the onLaunchDeepLink observer in MainScene. The link is stored as m.pendingDeepLink and is resolved in OnPlaylistDone() once the channel list is available.
Warm-start deep link (input event)
When the channel is already running and receives a deep link (e.g. from voice or another app), Roku sends anroInputEvent to the main message port:
scene.inputDeepLink triggers onInputDeepLink in MainScene, which calls ProcessDeepLink(). If the channel list is already loaded, ShowPlayer(idx) is called immediately. If the playlist has not finished loading yet, the link is stored in m.pendingDeepLink.
supports_input_launch=1 must be declared in the manifest for Roku to route input events to a running channel.Screen transition summary
| From | To | Trigger |
|---|---|---|
| (launch) | SplashScreen | MainScene.init() |
| SplashScreen | OnboardingScreen | No saved credentials |
| SplashScreen | LoadingLabel → AuthTask | Saved credentials found |
| OnboardingScreen | LoginScreen | User presses continue |
| LoginScreen | LoadingLabel → PlaylistTask | Login succeeds |
| AuthTask | LoadingLabel → PlaylistTask | Auto-login succeeds |
| PlaylistTask | PlayerScreen + MainScreen | Playlist loaded |
| PlayerScreen | MainScreen (overlay) | User requests overlay |
| MainScreen (overlay) | PlayerScreen | Channel selected or back |
| Any screen | SettingsScreen | Settings field set to true |
| SettingsScreen | Previous state | Close or logout |
| Any screen | LoginScreen | Logout or session expired |