Skip to main content
File: source/utils/Logger.brs

Purpose

Three-level logging facade. GTV_Log is gated on the IS_DEV_BUILD compile-time constant; GTV_Warn and GTV_Error always print.

Functions

sub GTV_Log(tag as String, msg as String)
    ' Prints only when IS_DEV_BUILD = true (bs_const in manifest)
    #if IS_DEV_BUILD
        print "[GTV][" + tag + "] " + msg
    #end if
end sub

sub GTV_Warn(tag as String, msg as String)
    print "[GTV][WARN][" + tag + "] " + msg
end sub

sub GTV_Error(tag as String, msg as String)
    print "[GTV][ERROR][" + tag + "] " + msg
end sub

Output format examples

FunctionExample output
GTV_Log("PlaylistTask", "Parsed 42 channels")[GTV][PlaylistTask] Parsed 42 channels
GTV_Warn("MainScene", "Auto-login failed")[GTV][WARN][MainScene] Auto-login failed
GTV_Error("HandshakeTask", "event=handshake_failed code=-1")[GTV][ERROR][HandshakeTask] event=handshake_failed code=-1
See Logging for full details on enabling dev logging and viewing output.
File: source/utils/HttpClient.brs

Purpose

HTTP request wrapper for all backend calls. Handles TLS certificates, platform headers, user-agent, async execution, and timeout cancellation. The function signature defaults to 15 000 ms; callers pass TIMEOUT_HTTP = 12 000 ms or TIMEOUT_AUTH = 15 000 ms explicitly.

Functions

function GTV_HttpGet(
    url       as String,
    timeoutMs as Integer = 15000
) as Object
Performs an async GET. Returns:
{ code: Integer, body: String, ok: Boolean }
' ok = (code >= 200 and code < 300)
' code = -1 on timeout or connection failure

function GTV_HttpPost(
    url       as String,
    jsonBody  as String,
    timeoutMs as Integer = 15000
) as Object
Performs an async POST with a JSON body. Same return shape as GTV_HttpGet.
function GTV_BuildQuery(params as Object) as String
Builds a URL-encoded query string from an AssocArray. Values are escaped with GTV_UrlEncode.
function GTV_UrlEncode(s as String) as String
Escapes a string using roUrlTransfer.Escape().
function GTV_BuildUserAgent(di = invalid as Dynamic) as String
Builds the User-Agent header string.Example: GlobalTV_Roku/1.0.7 (roku; Roku Express; 12.5.0)
function GTV_GetAppVersion() as String
function GTV_GetAppIdentity() as String
function GTV_GetBrandedDeviceModel(di = invalid as Dynamic) as String

Request headers set on every call

HeaderValue
Content-Typeapplication/json
X-Platformroku (PLATFORM constant)
User-AgentGTV_BuildUserAgent() result

Timeout constants (from AppConstants)

ConstantValueUsed for
TIMEOUT_HTTP12 000 msStandard requests (playlist, metrics, ads poll)
TIMEOUT_AUTH15 000 msAuth requests
TIMEOUT_HEALTH2 500 msHealth pings only
File: source/utils/RegistryManager.brs

Purpose

Thin wrapper around roRegistrySection for persistent key-value storage. All reads/writes use the registry section "GlobalTV" (REG_SECTION constant). Flush is called automatically on every write.

Core functions

function GTV_RegRead(key as String, defaultVal = "" as String) as String
sub     GTV_RegWrite(key as String, value as String)
sub     GTV_RegDelete(key as String)

Credential functions

function GTV_RegHasCredentials() as Boolean
function GTV_RegLoadCredentials() as Object
    ' Returns { username: String, password: String } or invalid
sub     GTV_RegSaveCredentials(username as String, password as String)
sub     GTV_RegClearCredentials()

Server / cache functions

function GTV_RegLoadLastServer() as String
sub     GTV_RegSaveLastServer(serverUrl as String)
sub     GTV_RegClearCache()
    ' Deletes REG_KEY_SERVER and REG_KEY_CHANNEL

Channel index functions

function GTV_RegLoadLastChannelIndex() as Integer
sub     GTV_RegSaveLastChannelIndex(idx as Integer)

Safe-area margin functions

function GTV_RegLoadSafeMarginPct() as Integer
    ' Clamped to [UI_SAFE_MARGIN_MIN_PCT, UI_SAFE_MARGIN_MAX_PCT]
sub     GTV_RegSaveSafeMarginPct(pct as Integer)

Registry key names (from AppConstants)

ConstantKey stringStores
REG_KEY_USER"username"Saved username
REG_KEY_PASS"password"Saved password
REG_KEY_SERVER"lastServer"Last active server URL
REG_KEY_CHANNEL"lastChannelIndex"Last viewed channel index
REG_KEY_SAFE_MARGIN"uiSafeMarginPct"UI safe-area margin percentage
REG_KEY_SERVER_PROFILES"serverProfiles"JSON-encoded server profile list
File: source/utils/ServerManager.brs

Purpose

Server list management. Maintains a list of server profiles (LAN and WAN), builds probe sequences with LAN-first retry behavior, resolves the active server, and provides CRUD operations on profiles.

Key functions

function GTV_LoadServerProfiles() as Object
    ' Returns array of sanitized server profiles from registry,
    ' falling back to GTV_DefaultServerProfiles() if none saved.

sub GTV_SaveServerProfiles(profiles as Object)

function GTV_ServerList() as Object
    ' Returns array of baseUrl strings from current profiles.

function GTV_FindActiveServer(forcedServer = "" as String) as String
    ' Probes the auto-probe list and returns the first reachable server URL.
    ' Saves it to registry via GTV_RegSaveLastServer().

function GTV_ServerBuildAutoProbeList() as Object
    ' Builds ordered probe list: LAN servers repeated SERVER_LAN_FORCE_RETRIES
    ' times, then WAN servers.

function GTV_ServerBuildRequestSequence(preferredBaseUrl = "" as String) as Object
    ' Like GTV_ServerBuildAutoProbeList() but puts preferredBaseUrl first.

function GTV_ServerInferType(baseUrl as String) as String
    ' Returns "lan" for RFC-1918 addresses (172.17.*, 192.168.*, 10.*,
    ' localhost), "wan" for everything else.

function GTV_ServerNormalizeBaseUrl(raw as Dynamic) as String
    ' Strips trailing slash, validates scheme (http/https).
    ' Returns "" for invalid URLs.

function GTV_ServerGetProfileById(profiles as Object, profileId as String) as Dynamic
function GTV_ServerGetProfileByBaseUrl(profiles as Object, baseUrl as String) as Dynamic

function GTV_ServerUpsertProfile(profiles as Object, profile as Object) as Object
function GTV_ServerDeleteProfile(profiles as Object, profileId as String) as Object
function GTV_ServerCanDelete(profiles as Object, profileId as String) as Boolean
    ' Returns false if deleting would leave the list empty.

function GTV_ServerCreateProfile(name as String, baseUrl as String, existing = invalid as Dynamic) as Dynamic
function GTV_ServerDescribe(profile as Dynamic) as String
    ' Returns a human-readable string: "Local [LAN] - http://172.17.11.2:3333"

Default server profiles

[
    {
        id      : "local_default"
        name    : "Local"
        baseUrl : "http://172.17.11.2:3333"
        type    : "lan"
        builtIn : true
        enabled : true
    },
    {
        id      : "public_default"
        name    : "Publico"
        baseUrl : "https://admin.globaltv.lat"
        type    : "wan"
        builtIn : true
        enabled : true
    }
]

LAN retry behavior

SERVER_LAN_FORCE_RETRIES = 3 — the LAN server URL is inserted 3 times at the head of the probe list before WAN servers are tried. This prioritizes the local server without completely blocking on a single failure.
File: source/utils/M3UParser.brs

Purpose

M3U8 playlist parser. Extracts channel metadata from #EXTINF lines and builds sorted channel and category arrays. Enforces or relaxes channel number requirements via PARSER_STRICT_CHANNEL_NUMBER.

Main function

function GTV_ParseM3U(text as String) as Object
Parses an M3U8 string. Returns:
{
    channels               : [],   ' sorted by channel number
    categories             : [],   ' deduplicated group-title values
    droppedMissingNumber   : 0,    ' entries dropped due to missing channel-number
    droppedDuplicateNumber : 0,    ' entries dropped due to duplicate number
    fallbackAssigned       : 0     ' entries assigned an auto-index (non-strict mode only)
}

Strict mode (PARSER_STRICT_CHANNEL_NUMBER = true)

When enabled (the default), any #EXTINF entry that does not have a valid channel-number attribute greater than 0 is dropped and counted in droppedMissingNumber. Duplicate channel numbers are also dropped.When disabled, entries without a channel-number receive an auto-incremented fallback index and are counted in fallbackAssigned.

Attribute extraction

function GTV_ExtractAttr(src as String, attrName as String) as String
    ' Extracts attrName="value" or attrName='value' from an #EXTINF line.
    ' Handles both double-quoted and single-quoted values.

Supported #EXTINF attributes

AttributeChannel field
tvg-idid
tvg-namename (falls back to trailing comma label)
tvg-logologo
group-titlegroup (default: "General")
channel-numbernumber

URL normalization

function GTV_NormalizeChannelUrl(rawUrl as String) as String
    ' hls://  -> http://
    ' hlss:// -> https://
    ' All others passed through unchanged.

Stream ID extraction

function GTV_ExtractStreamIdFromChannelUrl(rawUrl as String) as String
    ' Walks URL path segments in reverse, looking for a hex segment
    ' of >= 12 characters (likely a stream UUID). Used to populate
    ' channel.streamId and channel.contentId.

Sorting

Channels are sorted ascending by channel.number using an insertion sort (GTV_SortChannels).
File: source/utils/HealthCheck.brs

Purpose

Single-function HTTP health prober. Used by ServerManager, ConnectivityTask, and all tasks that need to determine whether a server is reachable before making a real request.

Function

function GTV_PingServer(baseUrl as String) as Boolean
Sends an async GET to baseUrl + PATH_HEALTH (/health) with a timeout of TIMEOUT_HEALTH = 2 500 ms.Returns true if the HTTP response code is in the range 200–499 (i.e., the server is up even if it returns a client error). Returns false on timeout, connection failure, or HTTP 5xx.

TLS

For https:// URLs, CERTS = "common:/certs/ca-bundle.crt" is applied automatically.

Usage pattern

if GTV_PingServer("https://admin.globaltv.lat")
    ' server is reachable
end if
File: source/utils/NetworkDetector.brs

Purpose

Device-level network state detection. Uses roDeviceInfo.GetConnectionType() to check whether the Roku device has any network interface active, without making an outbound HTTP request.

Functions

function GTV_IsOnline() as Boolean
    ' Returns true if roDeviceInfo.GetConnectionType() is non-empty.
    ' An empty string means no network interface is connected.
function GTV_GetConnectionType() as String
    ' Returns the raw connection type string from roDeviceInfo
    ' (e.g. "WiFiConnection", "WiredConnection", "").
function GTV_HasInternet(activeServer as String) as Boolean
    ' Combines GTV_IsOnline() with GTV_PingServer() for a full
    ' two-stage connectivity check:
    '   1. Device has a network interface (GTV_IsOnline)
    '   2. The active server health endpoint is reachable (GTV_PingServer)

Difference from HealthCheck

GTV_IsOnline() is a cheap local check (no network I/O). GTV_PingServer() makes an outbound HTTP call. ConnectivityTask uses both: GTV_IsOnline() writes to m.global.isOnline and GTV_PingServer() writes to m.global.hasInternet.