components_liveTv_LoadSheduleTask.bs
import "pkg:/source/api/ApiClient.bs"
import "pkg:/source/api/apiPool.bs"
import "pkg:/source/data/JellyfinDataTransformer.bs"
import "pkg:/source/roku_modules/log/LogMixin.brs"
import "pkg:/source/translationKeys.bs"
import "pkg:/source/utils/misc.bs"
sub init()
m.log = new log.Logger("LoadScheduleTask")
m.top.functionName = "loadSchedule"
end sub
' Orchestrator Task: fetches the programs for one block of channels and hands them back
' grouped by channel, so the guide can give each channel row its programs in one write.
'
' A fetch of a block's whole time window, or of the part before what it holds, sends minEndDate
' (programs still airing at its start or later); a fetch of the part after sends minStartDate
' (programs starting at or after what the block holds). The server compares both inclusively,
' so an extension repeats the programs the block holds at its edge, and the guide drops them
' (Schedule.applyPrograms).
sub loadSchedule()
channelIds = m.top.channelIds
params = {
UserId: m.global.user.id,
SortBy: "startDate",
EnableImages: false,
EnableTotalRecordCount: false,
EnableUserData: false,
channelIds: channelIds.join(","),
MaxStartDate: m.top.maxStartDate
}
if isValidAndNotEmpty(m.top.minStartDate)
params.MinStartDate = m.top.minStartDate
else
params.MinEndDate = m.top.minEndDate
end if
m.log.info("loadSchedule: starting fetch", "channels", channelIds.count(), "extend", isValidAndNotEmpty(m.top.minStartDate))
timer = CreateObject("roTimespan")
res = fetchRes(GetApi().BuildGetLiveTvScheduleRequest(params), "liveTvSchedule")
m.log.info("loadSchedule: fetch completed", "elapsed_ms", timer.TotalMilliseconds(), "ok", isValid(res) and res.ok)
byChannel = {}
for each id in channelIds
byChannel[id] = []
end for
ok = isValid(res) and res.ok and isValid(res.json) and isValid(res.json.Items)
if ok
' The array form, not transformBaseItem per program: the per-item form reads
' m.global.server.version for every program, a render-thread rendezvous each time, and
' while the guide scrolls each one waits on the animating grid: a block took most of a
' minute. The nodes are this thread's own, so reading them below crosses nothing.
transformed = JellyfinDataTransformer().transformBaseItemArray(res.json.Items)
for i = 0 to transformed.count() - 1
program = transformed[i]
programs = byChannel[program.channelId]
if isValid(programs)
' hdSmallIconUrl drives the TimeGrid recording indicator (a ContentNode built-in)
if isValidAndNotEmpty(program.timerId)
program.hdsmalliconurl = "pkg:/images/red.png"
else
program.hdsmalliconurl = ""
end if
programs.push(program)
end if
end for
end if
m.log.info("loadSchedule: result", "ok", ok, "elapsed_ms", timer.TotalMilliseconds())
m.top.ok = ok
m.top.programs = byChannel
end sub