class RokuBuilder::Navigator

Navigation methods

Public Class Methods

commands() click to toggle source
# File lib/roku_builder/plugins/navigator.rb, line 9
def self.commands
  {
    nav: {device: true},
    navigate: {device: true},
    type: {device: true},
    screen: {device: true},
    screens: {}
  }
end
parse_options(parser:, options:) click to toggle source
# File lib/roku_builder/plugins/navigator.rb, line 19
def self.parse_options(parser:, options:)
  parser.separator("Commands:")
  parser.on("-N", "--nav CMD", "Send the given command to the roku") do |n|
    options[:nav] = n
  end
  parser.on("--navigate", "Run interactive navigator") do
    options[:navigate] = true
  end
  parser.on("-y", "--type TEXT", "Type the given text on the roku device") do |t|
    options[:type] = t
  end
  parser.on("--screen SCREEN", "Show a screen") do |s|
    options[:screen] = s
  end
  parser.on("--screens", "Show possible screens") do
    options[:screens] = true
  end
end

Public Instance Methods

init() click to toggle source

Setup navigation commands

# File lib/roku_builder/plugins/navigator.rb, line 39
def init()
  @commands = {
    home: "Home",             rew: "Rev",                 ff: "Fwd",
    play: "Play",             select: "Select",           left: "Left",
    right: "Right",           down: "Down",               up: "Up",
    back: "Back",             replay: "InstantReplay",    info: "Info",
    backspace: "Backspace",   search: "Search",           enter: "Enter",
    volumedown: "VolumeDown", volumeup: "VolumeUp",       mute: "VolumeMute",
    channelup: "ChannelUp",   channeldown: "ChannelDown", tuner: "InputTuner",
    hdmi1: "InputHDMI1",      hdmi2: "InputHDMI2",        hdmi3: "InputHDMI3",
    hdmi4: "InputHDMI4",      avi: "InputAVI"
  }
  @screens = {
    platform: [:home, :home, :home, :home, :home, :ff, :play, :rew, :play, :ff],
    secret: [:home, :home, :home, :home, :home, :ff, :ff, :ff, :rew, :rew],
    secret2: [:home, :home, :home, :home, :home, :up, :right, :down, :left, :up],
    channels: [:home, :home, :home, :up, :up, :left, :right, :left, :right, :left],
    developer: [:home, :home, :home, :up, :up, :right, :left, :right, :left, :right],
    wifi: [:home, :home, :home, :home, :home, :up, :down, :up, :down, :up],
    antenna: [:home, :home, :home, :home, :home, :ff, :down, :rew, :down, :ff],
    bitrate: [:home, :home, :home, :home, :home, :rew, :rew, :rew, :ff, :ff],
    network: [:home, :home, :home, :home, :home, :right, :left, :right, :left, :right],
    reboot: [:home, :home, :home, :home, :home, :up, :rew, :rew, :ff, :ff]
  }
  @runable = [
    :secret, :channels
  ]
  mappings_init
end
nav(options:) click to toggle source

Send a navigation command to the roku device @param command [Symbol] The smbol of the command to send @return [Boolean] Success

navigate(options:) click to toggle source
screen(options:) click to toggle source

Show the commands for one of the roku secret screens @param type [Symbol] The type of screen to show @return [Boolean] Screen found

# File lib/roku_builder/plugins/navigator.rb, line 123
def screen(options:)
  type = options[:screen].to_sym
  unless @screens.has_key?(type)
    raise ExecutionError, "Unknown Screen"
  end
  if @runable.include?(type)
    nav(options: {nav: @screens[type].join(", ")})
  else
    @logger.unknown("Cannot run command automatically")
    display_screen_command(type)
  end
end
screens(options:) click to toggle source

Show avaiable roku secret screens

# File lib/roku_builder/plugins/navigator.rb, line 137
def screens(options:)
  logger = ::Logger.new(STDOUT)
  logger.formatter = proc {|_severity, _datetime, _progname, msg|
    "%s\n\r" % [msg]
  }
  logger.unknown("----------------------------------------------------------------------")
  @screens.keys.each {|screen|
    logger.unknown(sprintf("%10s: %s", screen.to_s, get_screen_command(screen)))
    logger.unknown("----------------------------------------------------------------------")
  }
end
type(options:) click to toggle source

Type text on the roku device @param text [String] The text to type on the device @return [Boolean] Success

# File lib/roku_builder/plugins/navigator.rb, line 90
def type(options:)
  conn = multipart_connection(port: 8060)
  options[:type].split(//).each do |c|
    path = "/keypress/LIT_#{CGI::escape(c)}"
    @logger.debug("Send Letter: "+path)
    response = conn.post path
    return false unless response.success?
  end
  return true
end

Private Instance Methods

display_screen_command(type) click to toggle source
# File lib/roku_builder/plugins/navigator.rb, line 219
def display_screen_command(type)
  logger = ::Logger.new(STDOUT)
  logger.formatter = proc {|_severity, _datetime, _progname, msg|
    "%s\n\r" % [msg]
  }
  logger.unknown(get_screen_command(type))
end
generate_maggings() click to toggle source
# File lib/roku_builder/plugins/navigator.rb, line 183
def generate_maggings
  mappings = {}
  if @config.input_mappings
    @config.input_mappings.each_pair {|key, value|
      unless "".to_sym == key
        key = key.to_s.sub(/\\e/, "\e").to_sym
        mappings[key] = value
      end
    }
  end
  mappings
end
get_screen_command(type) click to toggle source
# File lib/roku_builder/plugins/navigator.rb, line 227
def get_screen_command(type)
  display, count, string = [], [], ""
  @screens[type].each do |command|
    if display.count > 0 and  display[-1] == command
      count[-1] = count[-1] + 1
    else
      display.push(command)
      count.push(1)
    end
  end
  display.each_index do |i|
    if count[i] > 1
      string = string + @commands[display[i]]+" x "+count[i].to_s+", "
    else
      string = string + @commands[display[i]]+", "
    end
  end
  string.strip
end
handle_navigate_input(char) click to toggle source
# File lib/roku_builder/plugins/navigator.rb, line 211
def handle_navigate_input(char)
  if @mappings[char.to_sym] != nil
    nav(options: {nav: @mappings[char.to_sym][0]})
  elsif char.inspect.force_encoding("UTF-8").ascii_only?
    type(options: {type: char})
  end
end
mappings_init() click to toggle source
# File lib/roku_builder/plugins/navigator.rb, line 151
def mappings_init()
  @mappings = {
    "\e[1~": [ "home", "Home" ],
    "<": [ "rew", "<" ],
    ">": [ "ff", ">" ],
    "=": [ "play", "=" ],
    "\r": [ "select", "Enter" ],
    "\e[D": [ "left", "Left Arrow" ],
    "\e[C": [ "right", "Right Arrow" ],
    "\e[B": [ "down", "Down Arrow" ],
    "\e[A": [ "up", "Up Arrow" ],
    "\t": [ "back", "Tab" ],
    #"": [ "replay", "" ],
    "*": [ "info", "*" ],
    "\u007f": [ "backspace", "Backspace" ],
    "?": [ "search", "?" ],
    "\e\r": [ "enter", "Alt + Enter" ],
    "\e[5~": [ "volumeup", "Page Up" ],
    "\e[6~": [ "volumedown", "Page Down" ],
    "\e[4~": [ "mute", "End" ],
    #"": [ "channeldown", "" ],
    #"": [ "channelup", "" ],
    #"": [ "tuner", "" ],
    #"": [ "hdmi1", "" ],
    #"": [ "hdmi2", "" ],
    #"": [ "hdmi3", "" ],
    #"": [ "hdmi4", "" ],
    #"": [ "avi", "" ]
  }
  @mappings.merge!(generate_maggings) if @config.input_mappings
end
read_char() click to toggle source
# File lib/roku_builder/plugins/navigator.rb, line 196
def read_char
  STDIN.noecho do |io|
    io.raw!
    input = STDIN.getc.chr
    begin
      if input == "\e" then
        input << STDIN.read_nonblock(3) rescue nil
        input << STDIN.read_nonblock(2) rescue nil
      end
    end
    io.cooked!
    input
  end
end