source_utils_globals.bs

' Set all global variables that don't require an roSGNode
sub setGlobals()
  ' Initialize session content nodes
  serverNode = CreateObject("roSGNode", "JellyfinServer")
  userNode = CreateObject("roSGNode", "JellyfinUser")

  ' Initialize nested user nodes
  settingsNode = CreateObject("roSGNode", "JellyfinUserSettings")
  configNode = CreateObject("roSGNode", "JellyfinUserConfiguration")
  policyNode = CreateObject("roSGNode", "JellyfinUserPolicy")

  userNode.settings = settingsNode
  userNode.config = configNode
  userNode.policy = policyNode

  m.global.addFields({
    appLoaded: false,
    server: serverNode,
    user: userNode
  })
  ' Save Constants
  setConstants()
  ' Save information from roAppInfo to m.global.app
  SaveAppToGlobal()
  ' Save information from roDeviceInfo to m.global.device
  SaveDeviceToGlobal()
end sub

' Set all global variables that require an roSGNode
' NOTE: roSGNodes must be created after m.screen is shown
sub setGlobalNodes()
  playstateTask = CreateObject("roSGNode", "PlaystateTask")
  playstateTask.id = "playstateTask"
  m.global.addFields({ playstateTask: playstateTask })

  sceneManager = CreateObject("roSGNode", "SceneManager")
  sceneManager.observeField("dataReturned", m.port)
  m.global.addFields({ sceneManager: sceneManager })

  m.global.addFields({ queueManager: CreateObject("roSGNode", "QueueManager") })
  m.global.addFields({ audioPlayer: CreateObject("roSGNode", "AudioPlayer") })
end sub

' Save Constants
sub setConstants()
  ' Create Constants content node
  ' All constants are initialized in the XML with their default values
  constantsNode = CreateObject("roSGNode", "Constants")

  m.global.addFields({ constants: constantsNode })
end sub

' Save information from roAppInfo to m.global.app
sub SaveAppToGlobal()
  appInfo = CreateObject("roAppInfo")
  lastRunVersion = get_setting("LastRunVersion")

  ' Create and populate AppInfo content node
  appNode = CreateObject("roSGNode", "AppInfo")
  appNode.appId = appInfo.GetID()
  appNode.isDev = appInfo.IsDev()
  appNode.version = appInfo.GetVersion()
  appNode.lastRunVersion = lastRunVersion

  m.global.addFields({ app: appNode })
end sub

' Save information from roDeviceInfo to m.global.device
sub SaveDeviceToGlobal()
  deviceInfo = CreateObject("roDeviceInfo")

  ' remove special characters
  regex = CreateObject("roRegex", "[^a-zA-Z0-9\ \-\_]", "")
  filteredFriendly = regex.ReplaceAll(deviceInfo.getFriendlyName(), "")
  ' parse out serial
  displayName = deviceInfo.getModelDisplayName()
  deviceSerial = Mid(filteredFriendly, len(displayName) + 4)
  ' determine max playback resolution
  ' https://developer.roku.com/en-ca/docs/references/brightscript/interfaces/ifdeviceinfo.md#getvideomode-as-string
  videoMode = deviceInfo.GetVideoMode()
  iPos = Instr(1, videoMode, "i")
  pPos = Instr(1, videoMode, "p")
  videoHeight = invalid
  videoWidth = invalid
  refreshRate = "0"
  bitDepth = 8
  extraData = invalid
  heightToWidth = {
    "480": "720",
    "576": "720",
    "720": "1280",
    "1080": "1920",
    "2160": "3840",
    "4320": "7680"

  }
  if iPos > 0 and pPos = 0
    ' videMode = 000i
    videoHeight = mid(videoMode, 1, iPos - 1)
    ' save refresh rate
    if Len(videoMode) > iPos
      refreshRate = mid(videoMode, iPos + 1, 2)
    end if
    ' save whats left of string
    if Len(videoMode) > iPos + 2
      extraData = mid(videoMode, iPos + 3)
    end if
  else if iPos = 0 and pPos > 0
    ' videMode = 000p
    videoHeight = mid(videoMode, 1, pPos - 1)
    ' save refresh rate
    if Len(videoMode) > pPos
      refreshRate = mid(videoMode, pPos + 1, 2)
    end if
    ' save whats left of string
    if Len(videoMode) > pPos + 2
      extraData = mid(videoMode, pPos + 3)
    end if
  else
    'i and p not present in videoMode
    print "ERROR parsing deviceInfo.GetVideoMode()"
  end if
  videoWidth = heightToWidth[videoHeight]
  if isValid(extraData) and extraData = "b10" then bitDepth = 10
  if videoHeight = "4320" then bitDepth = 12

  ' Create and populate DeviceInfo content node
  deviceNode = CreateObject("roSGNode", "DeviceInfo")
  deviceNode.id = deviceInfo.getChannelClientID()
  deviceNode.uuid = deviceInfo.GetRandomUUID()
  deviceNode.name = displayName
  deviceNode.friendlyName = filteredFriendly
  deviceNode.serverDeviceName = deviceInfo.getChannelClientID()
  deviceNode.model = deviceInfo.GetModel()
  deviceNode.modelType = deviceInfo.GetModelType()
  deviceNode.modelDetails = deviceInfo.GetModelDetails()
  deviceNode.serial = deviceSerial
  deviceNode.osVersion = deviceInfo.GetOSVersion()
  deviceNode.locale = deviceInfo.GetCurrentLocale()
  deviceNode.clockFormat = deviceInfo.GetClockFormat()
  deviceNode.isAudioGuideEnabled = deviceInfo.IsAudioGuideEnabled()
  deviceNode.hasVoiceRemote = deviceInfo.HasFeature("voice_remote")
  deviceNode.displayType = deviceInfo.GetDisplayType()
  deviceNode.displayMode = deviceInfo.GetDisplayMode()
  ' video info below is based on the the Display type selected in the Roku settings which may or may not match the max playback resolution of the tv
  ' eg. if Display type is 1080p, these settings will be based on 1080p even if the TV supports 2160p/4K
  deviceNode.videoMode = videoMode
  deviceNode.videoHeight = StrToI(videoHeight)
  deviceNode.videoWidth = StrToI(videoWidth)
  deviceNode.videoRefresh = StrToI(refreshRate)
  deviceNode.videoBitDepth = bitDepth

  m.global.addFields({ device: deviceNode })
end sub