source_utils_globals.bs

' Set all global variables that don't require an roSGNode
sub setGlobals()
  m.global.addFields({ appLoaded: false })
  ' 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()
  m.global.addFields({
    constants: {
      colors: {
        primary: "0x8b5cf6FF",
        secondary: "0x3b82f6FF",
        text_primary: "0xf0f0f0FF",
        text_secondary: "0xa8a8a8FF",
        text_disabled: "0x4a4a4aFF",
        background_primary: "0x0d1117FF",
        background_secondary: "0x161b22FF",

        black_alpha_0: "0x00000000",
        black_alpha_10: "0x0000001A",
        black_alpha_20: "0x00000033",
        black_alpha_30: "0x0000004D",
        black_alpha_40: "0x00000066",
        black_alpha_50: "0x00000080",
        black_alpha_60: "0x00000099",
        black_alpha_70: "0x000000B3",
        black_alpha_80: "0x000000CC",
        black_alpha_90: "0x000000E6",
        black_alpha_100: "0x000000FF"
      },
      font_sizes: {
        smallest: 21,
        smaller: 25,
        small: 27,
        medium: 32,
        large: 42,
        larger: 50,
        largest: 60
      },
      icons: {
        arrow_up_black: "pkg:/images/icons/arrow-up-black.png",
        arrow_up_white: "pkg:/images/icons/arrow-up-white.png",
        arrow_down_black: "pkg:/images/icons/arrow-down-black.png",
        arrow_down_white: "pkg:/images/icons/arrow-down-white.png",
        check_black: "pkg:/images/icons/check-black.png",
        check_white: "pkg:/images/icons/check_white.png",
        tomato_fresh: "pkg:/images/icons/tomato-fresh.png",
        tomato_rotten: "pkg:/images/icons/tomato-rotten.png"
      },
      jellyfin_server_response: "jellyfin server"
    }
  })
end sub

' Save information from roAppInfo to m.global.app
sub SaveAppToGlobal()
  appInfo = CreateObject("roAppInfo")
  lastRunVersion = get_setting("LastRunVersion")
  m.global.addFields({
    app: {
      id: appInfo.GetID(),
      isDev: appInfo.IsDev(),
      version: appInfo.GetVersion(),
      lastRunVersion: lastRunVersion
    }
  })
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 extraData <> invalid and extraData = "b10" then bitDepth = 10
  if videoHeight = "4320" then bitDepth = 12

  m.global.addFields({
    device: {
      id: deviceInfo.getChannelClientID(),
      uuid: deviceInfo.GetRandomUUID(),
      name: displayName,
      friendlyName: filteredFriendly,
      serverDeviceName: deviceInfo.getChannelClientID(),
      model: deviceInfo.GetModel(),
      modelType: deviceInfo.GetModelType(),
      modelDetails: deviceInfo.GetModelDetails(),
      serial: deviceSerial,
      osVersion: deviceInfo.GetOSVersion(),
      locale: deviceInfo.GetCurrentLocale(),
      clockFormat: deviceInfo.GetClockFormat(),
      isAudioGuideEnabled: deviceInfo.IsAudioGuideEnabled(),
      hasVoiceRemote: deviceInfo.HasFeature("voice_remote"),

      displayType: deviceInfo.GetDisplayType(),
      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
      videoMode: videoMode,
      videoHeight: videoHeight,
      videoWidth: videoWidth,
      videoRefresh: StrToI(refreshRate),
      videoBitDepth: bitDepth
    }
  })
end sub