class InOurTime

Constants

AUDIO_DIRECTORY
CONFIG
CONFIG_DIR
CONFIG_NAME
DEFAULT_CONFIG
HERE
IN_OUR_TIME
ROOT
RSS_DIRECTORY

AUDIO_DIRECTORY = 'audio'.freeze

UPDATE_INTERVAL
VERSION

Public Class Methods

new() click to toggle source
# File lib/iot/iot.rb, line 188
def initialize
  Thread.abort_on_exception = true
  @queued = Array.new
  @content = String.new
  @selected = 0
  clear
  print "\e[?25h"
  setup
  load_config
  load_version
  load_help_maybe
  opening_title
  check_remote
  parse_rss
  sort_titles
  version_display_wait
  STDIN.echo = false
  STDIN.raw!
  run
end

Public Instance Methods

bottom_space?(bottom) click to toggle source
# File lib/iot/iot.rb, line 1123
def bottom_space? bottom
  bottom == ' '
end
build_program(bin) click to toggle source
# File lib/iot/iot.rb, line 473
def build_program(bin)
  title = bin['title'].shift.text
  { title:    title,
    subtitle: bin['itunes:subtitle'].shift.text,
    summary:  bin['itunes:summary'].shift.text,
    duration: bin['itunes:duration'].shift.text,
    date:     bin['pubDate'].shift.text[0..15],
    link:     bin['link'].shift.text,
    url:      bin['url'].shift,
    have_locally: have_locally?(title)
  }
end
build_programs(bin) click to toggle source
# File lib/iot/iot.rb, line 486
def build_programs bin
  bin['title'].size.times do
    @programs << build_program(bin)
  end
end
cfg_xy() click to toggle source
# File lib/iot/iot.rb, line 1053
def cfg_xy; [help_screen.size - 1, -1]       end
check_finished() click to toggle source
# File lib/iot/iot.rb, line 1338
def check_finished
  return if use_mpg123?
  return unless @playing
  return unless @play_time.ended?
  kill_audio
end
check_player_process() click to toggle source
# File lib/iot/iot.rb, line 1310
def check_player_process
  Process.kill 0, @pid
end
check_playing_time() click to toggle source
# File lib/iot/iot.rb, line 1354
def check_playing_time
  return unless @playing
  return unless @play_time.changed? unless use_mpg123?
  redraw
end
check_process() click to toggle source
# File lib/iot/iot.rb, line 1314
def check_process
  return unless @playing
  if @pid.is_a?(Integer)
    begin
      write_player("\e")
      sleep 0.1
      if @pid.is_a? Integer
        check_player_process
      end
    rescue Errno::ESRCH
      kill_audio
    end
  else
    kill_audio
    unless @queued.empty?
      title = @queued.shift
      prg = select_program(title)
      download prg
      run_program(prg)
      draw_by_title title
    end
  end
end
check_remote() click to toggle source
# File lib/iot/iot.rb, line 456
def check_remote
  update if update_remote?
end
check_tic() click to toggle source
# File lib/iot/iot.rb, line 1345
def check_tic
  return unless @tic.toc
  #    check_process if @tic.process
  #    check_finished if @tic.ended
  return unless @info.nil?
  return unless @help.nil?
  check_playing_time if @tic.playing_time
 end
clear() click to toggle source
# File lib/iot/iot.rb, line 673
def clear
  system('clear') || system('cls')
end
clear_content() click to toggle source
# File lib/iot/iot.rb, line 247
def clear_content
  @content.clear
end
clear_programs() click to toggle source
# File lib/iot/iot.rb, line 496
def clear_programs
  @programs = []
end
control_play?() click to toggle source
# File lib/iot/iot.rb, line 906
def control_play?
  @playing && use_mpg123?
end
create_config() click to toggle source
# File lib/iot/iot.rb, line 316
def create_config
  @config = YAML.load_file(DEFAULT_CONFIG)
  save_config
end
date() click to toggle source
# File lib/iot/iot.rb, line 641
def date
  @programs.map {|pr| return pr[:date] if pr[:title] == @playing}
end
dev_mode?() click to toggle source
# File lib/iot/iot.rb, line 272
def dev_mode?
  ENV['IN_OUR_TIME'] == 'development'.freeze
end
display_search_choice(results, choice) click to toggle source
# File lib/iot/iot.rb, line 716
def display_search_choice results, choice
  @key = KeyboardEvents.new
  begin
    if choice.to_i > 0 && choice.to_i < 6
      draw_by_title(results[choice.to_i - 1][0])
      return
    end
  end
  redraw
end
display_version() click to toggle source
# File lib/iot/iot.rb, line 302
def display_version
  iot_print("Loading ", :light_green) unless ARGV[0] == '-v' || ARGV[0] == '--version'
  iot_puts "In Our Time Player (#{@version})", :light_green
  quit if ARGV[0] == '-v' || ARGV[0] == '--version'
end
do_action(ip) click to toggle source
# File lib/iot/iot.rb, line 1291
def do_action ip
  case ip
  when :pause, :forward, :rewind, :jump_key, :page_forward, :page_back,
       :previous, :next, :play, :sort_key, :theme_toggle, :update_key,
       :info, :help, :quit_key, :search, :download_key, :enqueue,
       :next_program, :shuffle_key
    self.send ip
  end
end
do_configs() click to toggle source
# File lib/iot/iot.rb, line 372
def do_configs
  init_theme
  set_dimensions
  init_line_count
  @sort = @config[:sort]
end
do_events() click to toggle source
# File lib/iot/iot.rb, line 209
def do_events
  sleep 0.003
  sleep 0.1
end
download(prg) click to toggle source
# File lib/iot/iot.rb, line 764
def download prg
  return if prg[:have_locally]
  retries = 0
  clear_content
  iot_puts "Fetching #{prg[:title]}", @system_colour
  render
  10.times do
    begin
      res = Net::HTTP.get_response(URI.parse(prg[:url]))
    rescue SocketError => e
      print_error_and_delay "Error: Failed to connect to Internet! (#{e.class})"
      render
      @no_play = true
      break
    end
    case res
    when Net::HTTPFound
      iot_puts 'redirecting...', @system_colour
      render
      @doc = Oga.parse_xml(res.body)
      redirect = @doc.css("body p a").text
      break if download_audio(prg, redirect)
      sleep 2
    else
      print_error_and_delay 'Error! Failed to be redirected!'
      render
      @no_play = true
    end
    retries += 1
  end
  return if retries < 10
  print_error_and_delay "Max retries downloading #{prg[:title]}"
  render
  @no_play = true
end
download_audio(program, addr) click to toggle source
# File lib/iot/iot.rb, line 415
def download_audio(program, addr)
  res = Net::HTTP.get_response(URI.parse(addr))
  case res
  when Net::HTTPOK
    File.open(filename_from_title(program[:title]) , 'wb') do |f|
      iot_puts "writing #{File.basename(filename_from_title(program[:title]))}", @system_colour
      render
      sleep 0.2
      f.print(res.body)
      iot_puts " written.", @system_colour
      render
    end
    program[:have_locally] = true
  else
    iot_puts 'Download failed. Retrying...', @system_colour
    render
    nil
  end
end
download_key() click to toggle source
# File lib/iot/iot.rb, line 1267
def download_key
  title = @sorted_titles[@selected]
  pr = select_program title
  download pr
  draw_selected
end
draw_by_title(title) click to toggle source
# File lib/iot/iot.rb, line 550
def draw_by_title title
  @selected, @line_count = sort_selected(title)
  redraw
end
draw_page() click to toggle source
# File lib/iot/iot.rb, line 988
def draw_page
  clear_content
  if @line_count <= @titles_count
    @line_count.upto(@line_count + @page_height - 1) do |idx|
      if idx < @titles_count
        iot_print "> " if(idx == @selected) unless @config[:colour]
        show_count_maybe idx
        iot_puts @sorted_titles[idx], @selection_colour if (idx == @selected)
        iot_puts @sorted_titles[idx], @text_colour   unless(idx == @selected)
      end
    end
  else
    @line_count = 0
    0.upto(@page_height - 1) do |idx|
      iot_print "> ", @selection_colour if(idx == @selected)
      show_count_maybe(idx) unless @sorted_titles[idx].nil?
      iot_puts @sorted_titles[idx], @text_colour unless @sorted_titles[idx].nil?
    end
  end
  @line_count += @page_height
  print_playing_maybe
  render
end
draw_selected() click to toggle source
# File lib/iot/iot.rb, line 545
def draw_selected
  @line_count = get_line_count(@selected)
  redraw
end
end_selected() click to toggle source
# File lib/iot/iot.rb, line 563
def end_selected
  @selected == @titles_count - 1
end
end_title_focus() click to toggle source
# File lib/iot/iot.rb, line 571
def end_title_focus
  title_focus == @sorted_titles.last
end
enqueue() click to toggle source
# File lib/iot/iot.rb, line 1274
def enqueue
  @queued << @sorted_titles[@selected]
end
fetch_uri(uri, file) click to toggle source
# File lib/iot/iot.rb, line 402
def fetch_uri uri, file
  open(file, "wb") do |f|
    open(uri) do |ur|
      f.write(ur.read)
    end
  end
end
filename_from_title(title) click to toggle source
# File lib/iot/iot.rb, line 410
def filename_from_title title
  temp = title.gsub(/[^0-9a-z ]/i, '').tr(' ', '_').strip + '.mp3'
  File.join IN_OUR_TIME, AUDIO_DIRECTORY, temp.downcase
end
forward() click to toggle source
# File lib/iot/iot.rb, line 910
def forward
  return unless control_play?
  write_player ":"
  @play_time.forward unless use_mpg123?
end
get_line_count(idx) click to toggle source
# File lib/iot/iot.rb, line 529
def get_line_count idx
  idx += 1
  while idx % @page_height != 0
    idx += 1
  end
  idx
end
get_player() click to toggle source
# File lib/iot/iot.rb, line 660
def get_player
  return 'afplay' if @config[:mpg_player] == :afplay
  @config[:mpg_player].to_s
end
get_search_choice() click to toggle source
# File lib/iot/iot.rb, line 735
def get_search_choice
  print "Enter Choice: "
  temp = $stdin.getch.chomp
  temp == '0' ? :search_again : temp
end
get_search_results(search_term) click to toggle source
# File lib/iot/iot.rb, line 682
def get_search_results search_term
  distances = {}
  @sorted_titles.each do |title|
    title.split(' ').each do |word|
      if distances[title].nil?
        distances[title] = Levenshtein.distance(search_term, word)
      else
        distances[title] =
          distances[title] >
          Levenshtein.distance(search_term, word.downcase)   ?
            Levenshtein.distance(search_term, word.downcase) :
            distances[title]
      end
    end
  end
  results = distances.sort_by{ |k, v| v }
  results.shuffle! if search_term == ''
  results
end
get_search_term() click to toggle source
# File lib/iot/iot.rb, line 727
def get_search_term
  iot_puts "Enter Search Term or just Return for Random:", @system_colour, :now
  puts
  puts
  print "Search Term: "
  gets.chomp
end
have_locally?(title) click to toggle source
# File lib/iot/iot.rb, line 435
def have_locally? title
  filename = filename_from_title(title)
  File.exist?(filename) ? true : false
end
help() click to toggle source
# File lib/iot/iot.rb, line 1096
def help
  unless @help
    clear_content
    print_help
    @help = true
    render
  else
    redraw
    @help = nil
  end
end
help_cfg() click to toggle source
# File lib/iot/iot.rb, line 1057
def help_cfg;  help_partial(cfg_xy)          end
help_colour(scr) click to toggle source
# File lib/iot/iot.rb, line 1066
def help_colour scr
  case scr
  when :mpg
    return @selection_colour unless use_mpg123?
    @count_colour if use_mpg123?
  when :cfg
    @system_colour
  when :title
    @system_colour
  else
    @text_colour
  end
end
help_main() click to toggle source
# File lib/iot/iot.rb, line 1056
def help_main; help_partial(main_xy)         end
help_mpg() click to toggle source
# File lib/iot/iot.rb, line 1059
def help_mpg
  scr = help_partial(mpg_xy)
  scr[0].rstrip! << ' (enabled)  ' if     use_mpg123?
  scr[0].rstrip! << ' (disabled) ' unless use_mpg123?
  scr
end
help_option?() click to toggle source
# File lib/iot/iot.rb, line 1012
def help_option?
  ARGV[0] == '-h' || ARGV[0] == '--help' || ARGV[0] == '-?'
end
help_partial(x) click to toggle source
# File lib/iot/iot.rb, line 1054
def help_partial(x); help_screen[x[0]..x[1]] end
help_render(scr) click to toggle source
# File lib/iot/iot.rb, line 1084
def help_render scr
  txt = send "help_#{scr}"
  iot_puts txt.map{|x| x}.join("\n\r"), help_colour(scr)
end
help_screen() click to toggle source
# File lib/iot/iot.rb, line 1024
def help_screen
  []                                     <<
    " In Our Time Payer (#{@version}) "  <<
    "                                 "  <<
    " Play/Stop          - Enter/X    "  <<
    " Next/Prev          - Up/Down    "  <<
    " Next/Prev Page     - Right/Left "  <<
    " Arrange            - A          "  <<
    " Search             - ?          "  <<
    " Theme Toggle       - T          "  <<
    " Jump Around List   - J          "  <<
    " Update             - U          "  <<
    " Download           - D          "  <<
    " Enqueue            - E          "  <<
    " Shuffle Play       - S          "  <<
    " Shuffle Next       - N          "  <<
    " Info               - I          "  <<
    " Help               - H          "  <<
    " Quit               - Q          "  <<
    " mpg123 Control     -            "  <<
    "   Pause/Resume     - P/Spacebar "  <<
    "   Forward Skip     - F          "  <<
    "   Reverse Skip     - R          "  <<
    "Config: #{CONFIG}                "
end
help_title() click to toggle source
# File lib/iot/iot.rb, line 1055
def help_title; help_partial(title_xy)       end
idx_format(idx) click to toggle source
# File lib/iot/iot.rb, line 975
def idx_format idx
  sprintf("%03d", idx + 1)
end
info() click to toggle source
# File lib/iot/iot.rb, line 1203
def info
  clear_content
  case @info
  when nil
    prg = select_program @sorted_titles[@selected]
    print_subtitle prg
  when 1
    prg = select_program @sorted_titles[@selected]
    print_info prg
  when 2
    prg = select_program @sorted_titles[@selected]
    print_guests prg
  else
    redraw
    @info = nil
    return
  end
  render
end
init_countdown(duration) click to toggle source
# File lib/iot/iot.rb, line 820
def init_countdown(duration)
  @play_time = PlayTime.new(duration) unless use_mpg123?
end
init_line_count() click to toggle source
# File lib/iot/iot.rb, line 368
def init_line_count
  @line_count = @page_height
end
init_theme() click to toggle source
# File lib/iot/iot.rb, line 321
def init_theme
  theme = @config[:colour_theme]
  @selection_colour = @config[theme][:selection_colour]
  @count_sel_colour = @config[theme][:count_sel_colour]
  @count_colour     = @config[theme][:count_colour]
  @text_colour      = @config[theme][:text_colour]
  @system_colour    = @config[theme][:system_colour]
end
instructions() click to toggle source
# File lib/iot/iot.rb, line 922
def instructions
  iot_print "Type", @system_colour
  iot_print " h ", :light_green
  iot_print "for instructions", @system_colour
end
iot_print(x, col = @text_colour, now = false) click to toggle source
# File lib/iot/iot.rb, line 231
def iot_print x, col = @text_colour, now = false
  content = String.new
    content << x.colorize(col) if @config[:colour]
    content << x unless @config[:colour]
    unless now
      @content << content
    else
      $stdout << content
    end
end
iot_puts(x = '', col = @text_colour, now = false) click to toggle source
# File lib/iot/iot.rb, line 242
def iot_puts x = '', col = @text_colour, now = false
  iot_print x, col, now
  iot_print "\n\r", now
end
item_path(name) click to toggle source
# File lib/iot/iot.rb, line 492
def item_path name
  "rss/channel/item/#{name}"
end
jump_key() click to toggle source
# File lib/iot/iot.rb, line 587
def jump_key
  if top_or_end?
    if top_or_end_title_focus
      if top_selected
        list_end
      else
        list_top
      end
    else
      draw_by_title title_focus
    end
  else
    store_selected
    list_top_or_end
  end
end
justify(info) click to toggle source
# File lib/iot/iot.rb, line 1131
def justify info
  pages = [[],[]]
  page = 0
  top = 0
  bottom = @page_width
  loop do
    shift = top_space info[top..bottom]
    top = top + shift
    bottom = bottom + shift
    loop do
      idx = info[top..bottom].index("\n")
      if idx
        pages[page] << info[top..top + idx]
        page = 1
        bottom = top + idx + @page_width + 1
        top = top + idx + 1
      else
        break if bottom_space? info[bottom]
        bottom -= 1
      end
    end
    if last_line? info, top
      pages[page] << info[top..-1].strip
      break
    end
    pages[page] << info[top..bottom]
    top = bottom
    bottom = bottom + @page_width
  end
  pages
end
kill_audio() click to toggle source
# File lib/iot/iot.rb, line 958
def kill_audio
  loop do
    Thread.kill(@player_th) if @player_th
    return unless @playing
    begin
      break unless @pid.is_a?(Integer)
      Process.kill('QUIT', @pid)
      _, status = Process.wait2 @pid
      break if status.exited?
    rescue Errno::ESRCH
      break
    end
    sleep 0.2
  end
  reset
end
last_line?(info, top) click to toggle source
# File lib/iot/iot.rb, line 1127
def last_line? info, top
  info[top..-1].length < @page_width
end
list_end() click to toggle source
# File lib/iot/iot.rb, line 618
def list_end
  @selected = @titles_count - 1
  draw_selected
end
list_top() click to toggle source
# File lib/iot/iot.rb, line 613
def list_top
  @selected = 0
  draw_selected
end
list_top_or_end() click to toggle source
# File lib/iot/iot.rb, line 604
def list_top_or_end
  @list_top = @list_top? nil : true
  if @list_top
    list_top
  else
    list_end
  end
end
load_config() click to toggle source
# File lib/iot/iot.rb, line 379
def load_config
  create_config unless File.exist? CONFIG
  @config = YAML.load_file(CONFIG)
  do_configs
end
load_help_maybe() click to toggle source
# File lib/iot/iot.rb, line 1016
def load_help_maybe
  return unless help_option?
  @config[:colour] = false
  help
  puts
  exit 0
end
load_version() click to toggle source
# File lib/iot/iot.rb, line 308
def load_version
  File.open(VERSION) {|f| @version = f.readline.strip}
end
local_rss() click to toggle source
# File lib/iot/iot.rb, line 397
def local_rss
  [ "culture.rss", "history.rss", "in_our_time.rss",
    "philosophy.rss", "religion.rss", "science.rss"]
end
main_xy() click to toggle source
# File lib/iot/iot.rb, line 1051
def main_xy; [1, help_screen.size - 7]       end
mpg_xy() click to toggle source
# File lib/iot/iot.rb, line 1052
def mpg_xy; [help_screen.size - 6, -2]       end
next() click to toggle source
# File lib/iot/iot.rb, line 1241
def next
  return if @selected >= (@titles_count - 1)
  @selected += 1
  draw_selected
end
next_program() click to toggle source
# File lib/iot/iot.rb, line 1278
def next_program
  kill_audio
end
now() click to toggle source
# File lib/iot/iot.rb, line 256
def now
  Time.now.to_i
end
opening_title() click to toggle source
# File lib/iot/iot.rb, line 291
def opening_title
  return if dev_mode?
  puts_title :light_green
  render
  sleep 0.5
  clear_content
  puts_title @system_colour
  display_version
  render
end
page_back() click to toggle source
# File lib/iot/iot.rb, line 1229
def page_back
  @selected = @line_count - @page_height * 2
  @selected = @selected < 0 ? 0 : @selected
  draw_selected
end
page_forward() click to toggle source
# File lib/iot/iot.rb, line 1223
def page_forward
  return unless @line_count < @titles_count
  @selected = @line_count
  draw_selected
end
parse_rss() click to toggle source
# File lib/iot/iot.rb, line 500
def parse_rss
  clear_programs
  rss_files.each do |file|
    @doc = Oga.parse_xml(File.open(file))
    bin = {}
    tags.each do |tag|
      bin[tag] = [] if bin[tag].nil?
      bin[tag] = @doc.xpath(item_path(tag))
    end
    bin['url'] = []
    @doc.xpath(item_path('enclosure')).each do |x|
      bin['url'] << x.get('url')
    end
    build_programs(bin)
  end
  uniquify_programs
  @titles_count = @programs.length
end
pause() click to toggle source
# File lib/iot/iot.rb, line 897
def pause
  return unless control_play?
  @paused = @paused ? false : true
  @play_time.pause if @paused unless use_mpg123?
  @play_time.unpause unless @paused unless use_mpg123?
  write_player " "
  redraw
end
ping_player() click to toggle source
# File lib/iot/iot.rb, line 1306
def ping_player
  write_player("\e")
end
play() click to toggle source
# File lib/iot/iot.rb, line 1247
def play
  title = @sorted_titles[@selected]
  playing = @playing
  prg = select_program(title)
  download prg unless playing
  download prg if playing && (playing != title)
  kill_audio
  return unless (! playing) || (playing != title)
  run_program prg
  redraw
end
player_cmd() click to toggle source
# File lib/iot/iot.rb, line 665
def player_cmd
  if use_mpg123?
    "mpg123 -Cvk#{pre_delay}"
  else
    get_player
  end
end
pre_delay() click to toggle source
# File lib/iot/iot.rb, line 645
def pre_delay
  x = DateTime.strptime("Mon, 20 Jun 2016", '%a, %d %b %Y')
  y = DateTime.strptime(date, '%a, %d %b %Y')
  if y < x
    return '415' unless @playing == 'Abelard and Heloise'
    '0' if @playing == 'Abelard and Heloise'
  else
    '435'
  end
end
previous() click to toggle source
# File lib/iot/iot.rb, line 1235
def previous
  return if @selected <= 0
  @selected -= 1
  draw_selected
end
print_error_and_delay(message, delay = 2) click to toggle source
print_guests(prg) click to toggle source
print_help() click to toggle source
print_info(prg) click to toggle source
print_paused() click to toggle source
print_play_time() click to toggle source
print_playing() click to toggle source
print_playing_maybe() click to toggle source
print_program_details(prg) click to toggle source
print_search_results(results) click to toggle source
print_subtitle(prg) click to toggle source
puts_title(colour) click to toggle source
# File lib/iot/iot.rb, line 276
  def puts_title colour
    title =
      %q{  _____          ____               _______ _
 |_   _|        / __ \             |__   __(_)
   | |  _ __   | |  | |_   _ _ __     | |   _ _ __ ___   ___
   | | | '_ \  | |  | | | | | '__|    | |  | | '_ ` _ \ / _ \
  _| |_| | | | | |__| | |_| | |       | |  | | | | | | |  __/
 |_____|_| |_|  \____/ \__,_|_|       |_|  |_|_| |_| |_|\___|
}.freeze

    title.split("\n").map{|l| iot_print(l + "\r\n", colour)} if(window_width > 61)
    iot_puts("In Our Time\r", colour) unless(window_width > 61)
    iot_puts
  end
quit(code = 0) click to toggle source
# File lib/iot/iot.rb, line 214
def quit code = 0
  @key.kill if @key
  @tic.kill if @tic
  sleep 0.5
  STDIN.echo = true
  STDIN.cooked!
  puts "\n\n#{@error_msg}" if @error_msg
  puts 'Quitting...'.freeze
  sleep 0.5
  exit code
end
quit_key() click to toggle source
# File lib/iot/iot.rb, line 1286
def quit_key
  kill_audio
  quit
end
redraw() click to toggle source
# File lib/iot/iot.rb, line 636
def redraw
  @line_count -= @page_height
  draw_page
end
reformat(info) click to toggle source
# File lib/iot/iot.rb, line 1108
def reformat info
  ['With','Guests','Producer','Contributors'].map do |x|
    [' ', ':'].map do |y|
      [x, x.upcase].map do |z|
        info.gsub!(z + y, "\n" + z + y)
      end
    end
  end
  info
end
render() click to toggle source
# File lib/iot/iot.rb, line 251
def render
  clear
  $stdout << @content
end
reset() click to toggle source
# File lib/iot/iot.rb, line 880
def reset
  @pid = nil
  @playing = nil
  @paused = nil
  window_title
  redraw
end
reset_info_maybe(ip) click to toggle source
# File lib/iot/iot.rb, line 1301
def reset_info_maybe ip
  @info = nil unless ip == :info
  @help = nil unless ip == :help
end
rewind() click to toggle source
# File lib/iot/iot.rb, line 916
def rewind
  return unless control_play?
  write_player ";"
  @play_time.rewind unless use_mpg123?
end
rss_addresses() click to toggle source
# File lib/iot/iot.rb, line 389
def rss_addresses
  filename = "/episodes/downloads.rss"
  host = 'http://www.bbc.co.uk/programmes'
  [ "/b006qykl", "/p01drwny", "/p01dh5yg",
    "/p01f0vzr", "/p01gvqlg", "/p01gyd7j"
  ].collect{|page| host + page + filename}
end
rss_files() click to toggle source
# File lib/iot/iot.rb, line 440
def rss_files
  local_rss.map{|f| File.join IN_OUR_TIME, RSS_DIRECTORY, f }
end
rstrip_maybe(scr) click to toggle source
# File lib/iot/iot.rb, line 1080
def rstrip_maybe scr
  self.rstrip unless scr == :mpg
end
run() click to toggle source
# File lib/iot/iot.rb, line 1360
def run
  ip = ''
  @tic = Tic.new
  @key = KeyboardEvents.new
  redraw

  loop do
    loop do
      ip = @key.read
      break unless ip == :no_event
      check_tic
      do_events
    end
    reset_info_maybe ip
    do_action ip
    do_events
  end
end
run_program(prg) click to toggle source
# File lib/iot/iot.rb, line 824
def run_program prg
  unless @no_play
    @playing = prg[:title]
    player = player_cmd.split(' ').first
    unknown_player(player) unless which(File.basename player)
    window_title prg[:title]
    cmd = player_cmd + ' ' + filename_from_title(@playing)
    @messages = []
    init_countdown prg[:duration].to_i
    @player_th = Thread.new do
      buf = ''
      p_out, @p_in, @pid = PTY.spawn(cmd)
      sleep 1
      count = 0
      loop do
        unless use_mpg123?
          sleep 1
        else
          x = p_out.getc unless p_out.eof?
          if(((count >= 6) && (count <= 10)) ||
             ((count > 15) && (count < 21))  )
            buf << x
            count += 1
          elsif(((count == 0)  && (x == 'T'))  ||
                ((count == 1)  && (x == 'i'))  ||
                ((count == 2)  && (x == 'm'))  ||
                ((count == 3)  && (x == 'e'))  ||
                ((count == 4)  && (x == ':'))  ||
                ((count == 5)  && (x == ' '))  ||
                ((count >= 12) && (count <= 15)))
            count += 1
          elsif count == 11
            @running_time = buf
            buf = ''
            count += 1
          elsif count == 21
            @remaining_time = buf
            buf = ''
            count = 0
            sleep 0.3
            p_out.flush
          else
            count = 0
            sleep 0.001
          end
        end
      end
    end
  end
  @no_play = nil
end
save_config() click to toggle source
# File lib/iot/iot.rb, line 385
def save_config
  File.open(CONFIG, 'w') { |f| f.write @config.to_yaml}
end
search_init() click to toggle source
# File lib/iot/iot.rb, line 741
def search_init
  @key.kill
  sleep 0.2
  STDIN.echo = true
  STDIN.cooked!
  clear
  sleep 0.2
end
select_program(title) click to toggle source
# File lib/iot/iot.rb, line 519
def select_program title
  @programs.map{|pr| return pr if(pr[:title].strip == title.strip)}
  nil
end
set_dimensions() click to toggle source
# File lib/iot/iot.rb, line 363
def set_dimensions
  set_height
  set_width
end
set_height() click to toggle source
# File lib/iot/iot.rb, line 339
def set_height
  height = window_height
  while(((height - 2) % 10) != 0) ; height -= 1 ; end
  height = 10 if height < 10
  @page_height = height if(@config[:page_height] == :auto)
  @page_height = @config[:page_height] unless(@config[:page_height] == :auto)
end
set_width() click to toggle source
# File lib/iot/iot.rb, line 347
def set_width
  width = window_width
  while(width % 10 != 0) ; width -=1 ; end
  width = 20 if width < 20
  @page_width = width - 1 if(@config[:page_width] == :auto)
  @page_width = @config[:page_width] unless(@config[:page_width] == :auto)
end
setup() click to toggle source
# File lib/iot/iot.rb, line 260
def setup
  @start_time = Time.now
  iot = IN_OUR_TIME
  audio = File.join iot, AUDIO_DIRECTORY
  pages = File.join iot, RSS_DIRECTORY
  Dir.mkdir iot unless Dir.exist? iot
  Dir.mkdir audio unless Dir.exist? audio
  return if Dir.exist?(pages)
  Dir.mkdir pages
  local_rss.map{|f| FileUtils.touch(File.join pages, f)}
end
show_count_maybe(idx) click to toggle source
# File lib/iot/iot.rb, line 979
def show_count_maybe idx
  if have_locally?(@sorted_titles[idx])
    iot_print idx_format(idx), @count_sel_colour if @config[:show_count]
  else
    iot_print idx_format(idx), @count_colour if @config[:show_count]
  end
  iot_print ' '
end
shuffle_key() click to toggle source
# File lib/iot/iot.rb, line 1282
def shuffle_key
  @queued = @sorted_titles.shuffle
end
sort_key() click to toggle source
# File lib/iot/iot.rb, line 623
def sort_key
  title = @sorted_titles[@selected]
  toggle_sort
  draw_by_title title
end
sort_selected(title) click to toggle source
# File lib/iot/iot.rb, line 537
def sort_selected title
  @sorted_titles.each_with_index do |st, sel|
    if st == title
      return sel, get_line_count(sel)
    end
  end
end
sort_titles() click to toggle source
# File lib/iot/iot.rb, line 524
def sort_titles
  @sorted_titles = @programs.collect { |pr| pr[:title] }
  @sorted_titles.sort_by!(&:downcase) unless @sort == :age
end
store_selected() click to toggle source
# File lib/iot/iot.rb, line 579
def store_selected
  @last_selected = @selected
end
tags() click to toggle source
# File lib/iot/iot.rb, line 467
def tags
  ['title', 'itunes:subtitle',
   'itunes:summary', 'itunes:duration',
   'pubDate', 'link']
end
theme_toggle() click to toggle source
# File lib/iot/iot.rb, line 330
def theme_toggle
  theme = @config[:colour_theme]
  @config[:colour_theme] = theme == :light_theme ?
                             :dark_theme : :light_theme
  save_config
  init_theme
  redraw
end
title_focus() click to toggle source
# File lib/iot/iot.rb, line 555
def title_focus
  @playing ? @playing : (@sorted_titles[@last_selected || 0])
end
title_xy() click to toggle source
# File lib/iot/iot.rb, line 1050
def title_xy; [0,0]                          end
toggle_sort() click to toggle source
# File lib/iot/iot.rb, line 629
def toggle_sort
  @sort = @sort == :age ? :alphabet : :age
  @config[:sort] = @sort
  save_config
  sort_titles
end
top_or_end?() click to toggle source
# File lib/iot/iot.rb, line 575
def top_or_end?
  top_selected || end_selected
end
top_or_end_title_focus() click to toggle source
# File lib/iot/iot.rb, line 583
def top_or_end_title_focus
  top_title_focus || end_title_focus
end
top_selected() click to toggle source
# File lib/iot/iot.rb, line 559
def top_selected
  @selected == 0
end
top_space(info) click to toggle source
# File lib/iot/iot.rb, line 1119
def top_space info
  info.length - info.lstrip.length
end
top_title_focus() click to toggle source
# File lib/iot/iot.rb, line 567
def top_title_focus
  title_focus == @sorted_titles.first
end
uniquify_programs() click to toggle source
# File lib/iot/iot.rb, line 460
def uniquify_programs
  @programs.uniq!{|pr| pr[:title]}
  return if @programs.uniq.length == @programs.length
  print_error_and_delay "Error ensuring Programs unique!"
  quit 1
end
unknown_player(cmd) click to toggle source
# File lib/iot/iot.rb, line 815
def unknown_player cmd
  @error_msg = "Error: Unknown MPG Player: #{cmd}\r"
  quit 1
end
update() click to toggle source
# File lib/iot/iot.rb, line 444
def update
  clear_content
  clear
  iot_print "Checking rss feeds ", @system_colour, :now
  local_rss.length.times do |count|
    iot_print '.', @system_colour, :now
    fetch_uri rss_addresses[count], rss_files[count]
  end
  @config[:last_update] = now
  save_config
end
update_key() click to toggle source
# File lib/iot/iot.rb, line 1259
def update_key
  update
  parse_rss
  sort_titles
  @selected = 0
  draw_selected
end
update_remote?() click to toggle source
# File lib/iot/iot.rb, line 312
def update_remote?
  now - @config[:update_interval] > @config[:last_update]
end
use_mpg123?() click to toggle source
# File lib/iot/iot.rb, line 656
def use_mpg123?
  @config[:mpg_player] == :mpg123
end
version_display_wait() click to toggle source
# File lib/iot/iot.rb, line 226
def version_display_wait
  return if dev_mode?
  do_events while Time.now - @start_time < 1.5
end
which(cmd) click to toggle source

Cross-platform way of finding an executable in the $PATH.

which('ruby') #=> /usr/bin/ruby
# File lib/iot/iot.rb, line 804
def which(cmd)
  exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
  ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
    exts.each { |ext|
      exe = File.join(path, "#{cmd}#{ext}")
      return exe if File.executable?(exe) && !File.directory?(exe)
    }
  end
  return nil
end
window_height() click to toggle source
# File lib/iot/iot.rb, line 355
def window_height
  $stdout.winsize.first
end
window_title(title = '') click to toggle source
# File lib/iot/iot.rb, line 876
def window_title title = ''
  STDOUT.puts "\"\033]0;#{title}\007"
end
window_width() click to toggle source
# File lib/iot/iot.rb, line 359
def window_width
  $stdout.winsize[1]
end
write_player(str) click to toggle source
# File lib/iot/iot.rb, line 888
def write_player str
  begin
    @p_in.puts str
  rescue Errno::EIO
    kill_audio
    reset
  end
end