content: '******************************************************
  ' Get the Base Url of the MB Server
  '******************************************************
  
  Function GetServerBaseUrl(baseUrl = "")
  
  	if baseUrl = "" then baseUrl = GetViewController().serverUrl
  	
  	if baseurl = invalid then
  		m.viewcontroller.logout()
  		return invalid
  	end if
  
  	if Instr(0, baseUrl, "://") = 0 then 
  		baseUrl = "http://" + baseUrl
  	end if
  	
      return baseUrl + "/emby"
  End Function
  
  
  '******************************************************
  ' Source: Plex Roku Client
  '         https://github.com/plexinc/roku-client-public
  ' Return the first IP address of the Roku device
  '******************************************************
  
  Function GetFirstIPAddress()
      device = CreateObject("roDeviceInfo")
      addrs = device.GetIPAddrs()
      addrs.Reset()
      if addrs.IsNext() then
          return addrs[addrs.Next()]
      else
          return invalid
      end if
  End Function
  
  
  '******************************************************
  ' Source: Plex Roku Client
  '         https://github.com/plexinc/roku-client-public
  ' Scan Network to find local MB Server through UDP
  '******************************************************
  
  Function scanLocalNetwork() As Dynamic
  
      ' Setup Broadcast message and port
      broadcastMessage = "who is EmbyServer?"
      broadcastPort = 7359
  
      success = false
      attempts = 0
  
      ' Setup multicast fallback
      multicast = "239.0.0.250"
      ip = multicast
  
      subnetRegex = CreateObject("roRegex", "((\d+)\.(\d+)\.(\d+)\.)(\d+)", "")
      addr = GetFirstIPAddress()
      if addr <> invalid then
          match = subnetRegex.Match(addr)
          if match.Count() > 0 then
              ip = match[1] + "255"
              Debug("Using broadcast address " + ip)
          end if
      end if
  
      ' Attempt multiple times in case sending message fails
      while attempts < 10
          ' Setup UDP
          udp  = CreateObject("roDatagramSocket")
          port = CreateObject("roMessagePort")
          udp.setMessagePort(port)
          udp.setBroadcast(true)
  
          ' Loop multiple times to make send to address stick
          for i = 0 to 5
              addr = CreateObject("roSocketAddress")
              addr.setHostName(ip)
              addr.setPort(broadcastPort)
              udp.setSendToAddress(addr)
  
              sendTo = udp.getSendToAddress()
              if sendTo <> invalid
                  sendToStr = tostr(sendTo.getAddress())
                  addrStr = tostr(addr.getAddress())
                  Debug("Send To Address: " + sendToStr + " / " + addrStr)
                  if sendToStr = addrStr
                      exit for
                  end If
              end if
  
              Debug("Failed To Set Send To Address")
          end for
  
          udp.notifyReadable(true) 
  
          ' Send Broadcast Message
          bytes = udp.sendStr(broadcastMessage)
  
          if bytes > 0
              success = udp.eOK()
          else
              success = false
              if bytes = 0
                  Debug("Falling back to multicast address")
                  ip = multicast
                  try = 0
              end if
          end if
  
          if success
              exit while
          else if attempts = 9 AND ip <> multicast then
              Debug("Falling back to multicast address")
              ip = multicast
              attempts = 0
          else
              sleep(500)
              Debug("Retrying, errno " + tostr(udp.status()))
              attempts = attempts + 1
          end If
      end while
  
      ' Only Do Event Loop If Successful Message Sent
      if success
          while true
              msg = wait(5000, port)
  
              if type(msg) = "roSocketEvent" And msg.getSocketID() = udp.getID() And udp.isReadable()
                  receivedMessage = udp.receiveStr(512) ' max 512 characters
                  Debug("Received Message: " + receivedMessage)
                  udp.close()
                  return ParseJSON(receivedMessage)
              else if msg = invalid
                  Debug("Cancel UDP Broadcast")
                  udp.close()
                  return invalid
              end if
          end while
  
      end if
  
      return invalid
  End Function
  
  function findServers() as Object
  
  	server = scanLocalNetwork()
  	
  	servers = CreateObject("roArray", 10, true)
  	
  	if server <> invalid then
  	
  		servers.push({
  		
  			LocalAddress: server.Address,
  			Name: server.Name,
  			Id: server.Id
  		})
  		
  	end if
  	
  	return servers
  
  End function
  
  '******************************************************
  ' Authenticates a user by name
  '******************************************************
  
  Function authenticateUser(serverUrl As String, userText As String, passwordText As String) As Object
  
      if passwordText <> "" then
          ba = CreateObject("roByteArray")
          ba.FromAsciiString(passwordText)
  
          digest = CreateObject("roEVPDigest")
          digest.Setup("sha1")
          sha1Password = digest.Process(ba)
      else
          sha1Password = "da39a3ee5e6b4b0d3255bfef95601890afd80709"
      end if
  
      ' URL
      url = GetServerBaseUrl(serverUrl) + "/Users/AuthenticateByName?format=json"
  
      ' Prepare Request
      request = HttpRequest(url)
      request.AddAuthorization()
  
      ' Execute Request
      response = request.PostFromStringWithTimeout("Username=" + HttpEncode(userText) + "&Password=" + sha1Password, 5)
      if response <> invalid
          metaData = ParseJSON(response)
  
          if metaData = invalid
  	    createDialog("Authentication Error!", "Error parsing authentication response.", "OK", true)
              Debug("Error parsing authentication response.")
              return invalid
          end if
  
          return metaData
      else
          createDialog("Authentication Error!", "Invalid username or password.", "OK", true)
          Debug("Invalid username or password.")
      end if
      createDialog("Authentication Error!", "An unknown problem has occured.", "OK", true)
      return invalid
  End Function
  
  '******************************************************
  ' Post capabilities
  '******************************************************
  
  Function postCapabilities() As Boolean
  
  	Debug("Posting capabilities")
  	
      url = GetServerBaseUrl() + "/Sessions/Capabilities/Full"
  	
  	caps = getCapabilities()
  
  	' Prepare Request
  	request = HttpRequest(url)
  	request.AddAuthorization()
  	request.ContentType("json")
  
  	json = SimpleJSONBuilder(caps)
   	response = request.PostFromStringWithTimeout(json, 5)
  
  	if response <> invalid
  		return true
  	else
  		createDialog("Capabilities Error!", "Failed to Post Capabilities.", "OK", true)
  		Debug("Failed to Post Capabilities")
  	end if
  	return false
  End Function
  
  '******************************************************
  ' Get Session Id
  '******************************************************
  
  Function GetSessionId() As String
  
  	Debug("Getting SessionId")
  	
      	url = GetServerBaseUrl() + "/Sessions?DeviceId=" + getGlobalVar("rokuUniqueId")
  
  	' Prepare Request
  	request = HttpRequest(url)
  	request.ContentType("json")
  	request.AddAuthorization()
  	
  
  	' Execute Request
  	response = request.GetToStringWithTimeout(20)
  
  	if response <> invalid
          	fixedResponse	= normalizeJson(response)
          	jsonObj		= ParseJSON(fixedResponse)
  		debug("Session ID :"+jsonObj[0].Id)
  		return jsonObj[0].Id
  	else
  		createDialog("Sessions Error!", "Failed to Get Sessions Id.", "OK", true)
  		Debug("Failed to Get Sessions")
  	end if
  	return invalid
  End Function
  
  
  '******************************************************
  ' normalizeJson
  '******************************************************
  Function normalizeJson(json As String) as String
  
  	' Fixes bug within BRS Json Parser
  	regex         = CreateObject("roRegex", Chr(34) + "(RunTimeTicks|PlaybackPositionTicks|StartPositionTicks)" + Chr(34) + ":(-?[0-9]+)(}?]?),", "i")
  	json = regex.ReplaceAll(json, Chr(34) + "\1" + Chr(34) + ":" + Chr(34) + "\2" + Chr(34) + "\3,")
  
  	return json
  	
  End Function
  
  Function getInstalledPlugins() As Object
  
      ' URL
      url = GetServerBaseUrl() + "/Plugins"
  
      ' Prepare Request
      request = HttpRequest(url)
      request.ContentType("json")
      request.AddAuthorization()
  
      ' Execute Request
      response = request.GetToStringWithTimeout(10)
      if response <> invalid
  	fixedResponse = normalizeJson(response)
          return ParseJSON(fixedResponse)
      else
          createDialog("Plugins Error!", "Error occured retrieving plugins.", "OK", true)
      end if
      createDialog("Plugins Error!", "An unknown error has occured.", "OK", true)
      return invalid
  End Function