in_our_time 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d9043f6f2dbe432df896bf146dd287d879aa5869
4
+ data.tar.gz: c1952b8d0ea58b5a4019a9842b1ad36078683bb3
5
+ SHA512:
6
+ metadata.gz: 9e09695c6a2cbe9f8ee92220461bfb8d749be4c2edc469a16de2e18acecc3364aed07d482ae9d22b37a8917312b7a85f878e98b1e027613b3f5dc483dc6a569e
7
+ data.tar.gz: 9fba64691995283bce6b0737676056e118a68f413d380cb3a9001bfd4a1b65709d5e29148f756bd55992cbd65562d88500745e20647a1eecd3ce20510bb87280
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ /audio/
2
+ /rss/
3
+ /in_our_time.org
4
+ /config.yml
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ # A sample Gemfile
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'rake/version_task'
4
+ require 'yard'
5
+
6
+ Rake::VersionTask.new
7
+
8
+ Rake::TestTask.new do |t|
9
+ t.pattern = "test/test_*.rb"
10
+ end
11
+
12
+ YARD::Rake::YardocTask.new do |t|
13
+ t.files = ['lib/**/*.rb']
14
+ t.options = ['--any', '--extra', '--opts']
15
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/bin/iot ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ puts Dir.pwd
4
+ require 'lib/in_our_time.rb'
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'in_our_time'
7
+ spec.version = File.read('VERSION')
8
+ spec.date = '2016-09-26'
9
+ spec.authors = ["Martyn Jago"]
10
+ spec.email = ["martyn.jago@btinternet.com"]
11
+ spec.description = "In Our Time Player"
12
+ spec.summary = "Select, play, and download BBC \'In Our Time\' podcasts - all from the command line"
13
+ spec.homepage = 'https://github.com/mjago/In_Our_Time'
14
+ spec.files = `git ls-files`.split($/)
15
+ spec.executables = "iot"
16
+ spec.bindir = 'bin'
17
+ spec.license = 'MIT'
18
+
19
+ spec.require_paths = ["lib"]
20
+ spec.required_ruby_version = '>= 2.0.0'
21
+ spec.add_runtime_dependency 'nokogiri', '>= 1.6.8'
22
+ spec.add_development_dependency 'version', '>= 1.0.0'
23
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'iot/iot.rb'
2
+ require_relative 'iot/colour_prompt.rb'
3
+
4
+ InOurTime.new
@@ -0,0 +1,129 @@
1
+ # ==========================================
2
+ # Unity Project - A Test Framework for C
3
+ # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
4
+ # [Released under MIT License. Please refer to license.txt for details]
5
+ # ==========================================
6
+
7
+ if RUBY_PLATFORM =~/(win|w)32$/
8
+ begin
9
+ require 'Win32API'
10
+ rescue LoadError
11
+ puts "ERROR! \"Win32API\" library not found"
12
+ puts "\"Win32API\" is required for colour on a windows machine"
13
+ puts " try => \"gem install Win32API\" on the command line"
14
+ puts
15
+ end
16
+ # puts
17
+ # puts 'Windows Environment Detected...'
18
+ # puts 'Win32API Library Found.'
19
+ # puts
20
+ end
21
+
22
+ class ColourCommandLine
23
+ def initialize
24
+ if RUBY_PLATFORM =~/(win|w)32$/
25
+ get_std_handle = Win32API.new("kernel32", "GetStdHandle", ['L'], 'L')
26
+ @set_console_txt_attrb =
27
+ Win32API.new("kernel32","SetConsoleTextAttribute",['L','N'], 'I')
28
+ @hout = get_std_handle.call(-11)
29
+ end
30
+ end
31
+
32
+ def change_to(new_colour)
33
+ if RUBY_PLATFORM =~/(win|w)32$/
34
+ @set_console_txt_attrb.call(@hout,self.win32_colour(new_colour))
35
+ else
36
+ "\033[30;#{posix_colour(new_colour)};22m"
37
+ end
38
+ end
39
+
40
+ def win32_colour(colour)
41
+ case colour
42
+ when :black then 0
43
+ when :dark_blue then 1
44
+ when :dark_green then 2
45
+ when :dark_cyan then 3
46
+ when :dark_red then 4
47
+ when :dark_purple then 5
48
+ when :dark_yellow, :narrative then 6
49
+ when :default_white, :default, :dark_white then 7
50
+ when :silver then 8
51
+ when :blue then 9
52
+ when :green, :success then 10
53
+ when :cyan, :output then 11
54
+ when :red, :failure then 12
55
+ when :purple then 13
56
+ when :yellow then 14
57
+ when :white then 15
58
+ else
59
+ 0
60
+ end
61
+ end
62
+
63
+ def posix_colour(colour)
64
+ # ANSI Escape Codes - Foreground colors
65
+ # | Code | Color |
66
+ # | 39 | Default foreground color |
67
+ # | 30 | Black |
68
+ # | 31 | Red |
69
+ # | 32 | Green |
70
+ # | 33 | Yellow |
71
+ # | 34 | Blue |
72
+ # | 35 | Magenta |
73
+ # | 36 | Cyan |
74
+ # | 37 | Light gray |
75
+ # | 90 | Dark gray |
76
+ # | 91 | Light red |
77
+ # | 92 | Light green |
78
+ # | 93 | Light yellow |
79
+ # | 94 | Light blue |
80
+ # | 95 | Light magenta |
81
+ # | 96 | Light cyan |
82
+ # | 97 | White |
83
+
84
+ case colour
85
+ when :black then 30
86
+ when :red, :failure then 31
87
+ when :green, :success then 32
88
+ when :yellow then 33
89
+ when :blue, :narrative then 34
90
+ when :purple, :magenta then 35
91
+ when :cyan, :output then 36
92
+ when :white, :default_white then 37
93
+ when :default then 39
94
+ when :dark_gray then 90 # Dark gray
95
+ when :light_red then 91 # Light red
96
+ when :light_green then 92 # Light green
97
+ when :light_yellow then 93 # Light yellow
98
+ when :light_blue then 94 # Light blue
99
+ when :light_magenta then 95 # Light magenta
100
+ when :light_cyan then 96 # Light cyan
101
+ when :White then 97 # White
102
+
103
+ else
104
+ 39
105
+ end
106
+ end
107
+
108
+ def out_c(mode, colour, str, out = :stdout)
109
+ buf = case out
110
+ when :stdout
111
+ $stdout
112
+ else
113
+ out = out
114
+ end
115
+ case RUBY_PLATFORM
116
+ when /(win|w)32$/
117
+ change_to(colour)
118
+ buf.puts str if mode == :puts
119
+ buf.print str if mode == :print
120
+ change_to(:default_white)
121
+ else
122
+ buf.puts("#{change_to(colour)}#{str}\033[0m") if mode == :puts
123
+ $stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print
124
+ end
125
+ end
126
+ end # ColourCommandLine
127
+
128
+ def colour_puts(role,str, out = :stdout) ColourCommandLine.new.out_c(:puts, role, str, out) end
129
+ def colour_print(role,str, out = :stdout) ColourCommandLine.new.out_c(:print, role, str, out) end
data/lib/iot/iot.rb ADDED
@@ -0,0 +1,539 @@
1
+ require 'nokogiri'
2
+ require 'rss'
3
+ require 'open-uri'
4
+ require 'net/http'
5
+ require 'open-uri'
6
+ require 'yaml'
7
+ require 'fileutils'
8
+
9
+ class InOurTime
10
+ ROOT = File.expand_path '~/'
11
+ IN_OUR_TIME = File.join ROOT, '.in_our_time'
12
+ CONFIG = File.join IN_OUR_TIME, 'config.yml'
13
+ UPDATE_INTERVAL = 604800
14
+ AUDIO_DIRECTORY = 'audio'
15
+ RSS_DIRECTORY = 'rss'
16
+ PAGE_HEIGHT = 20
17
+ PAGE_WIDTH = 80
18
+
19
+ class KeyboardEvents
20
+
21
+ @arrow = 0
22
+
23
+ def input
24
+ sleep 0.001
25
+ begin
26
+ system("stty raw -echo")
27
+ str = STDIN.getc
28
+ ensure
29
+ system("stty -raw echo")
30
+ end
31
+
32
+ case @arrow
33
+ when 1
34
+ if str == "["
35
+ @arrow = 2
36
+ else
37
+ @arrow = 0
38
+ end
39
+
40
+ when 2
41
+ return :previous if str == "A"
42
+ return :next if str == "B"
43
+ return :page_forward if str == "C"
44
+ return :previous if str == "D"
45
+ @arrow = 0
46
+ end
47
+
48
+ case str
49
+ when "\e"
50
+ @arrow = 1
51
+ when "l",'L'
52
+ :list
53
+ when ' '
54
+ :page_forward
55
+ when "q",'Q', "\u0003", "\u0004"
56
+ :quit
57
+ when 'p', 'P'
58
+ :previous
59
+ when 'n', 'N'
60
+ :next
61
+ when 's', 'S'
62
+ :stop
63
+ when 'x', 'X', "\r"
64
+ :play
65
+ when 'i', 'I'
66
+ :info
67
+ when '?', 'h'
68
+ :help
69
+ else
70
+ :unknown
71
+ end
72
+ end
73
+ end
74
+
75
+ def initialize
76
+ @programs, @selected = [], 0
77
+ setup
78
+ load_config
79
+ check_remote
80
+ parse_rss
81
+ sort_titles
82
+ run
83
+ end
84
+
85
+ def iot_print x, role = :default
86
+ colour_print(role, x) if @config[:colour]
87
+ print(x) unless @config[:colour]
88
+ end
89
+
90
+ def iot_puts x, role = :default
91
+ colour_puts(role, x) if @config[:colour]
92
+ puts(x) unless @config[:colour]
93
+ end
94
+
95
+ def now
96
+ Time.now.to_i
97
+ end
98
+
99
+ def setup
100
+ iot = IN_OUR_TIME
101
+ audio = File.join iot, AUDIO_DIRECTORY
102
+ pages = File.join iot, RSS_DIRECTORY
103
+ Dir.mkdir iot unless Dir.exist? iot
104
+ Dir.mkdir audio unless Dir.exist? audio
105
+ unless Dir.exist? pages
106
+ Dir.mkdir pages
107
+ local_rss.map{|f| FileUtils.touch(File.join pages, f)}
108
+ end
109
+ end
110
+
111
+ def update_remote?
112
+ now - @config[:update_interval] > @config[:last_update]
113
+ end
114
+
115
+ def new_config
116
+ {:last_update => now - UPDATE_INTERVAL - 1,
117
+ :update_interval => UPDATE_INTERVAL,
118
+ :colour => true,
119
+ :mpg_player => :afplay,
120
+ :sort => :age,
121
+ :show_count => true,
122
+ :page_height => PAGE_HEIGHT,
123
+ :page_width => PAGE_WIDTH
124
+ }
125
+ end
126
+
127
+ def load_config
128
+ unless File.exist? CONFIG
129
+ save_config new_config
130
+ end
131
+ @config = YAML::load_file(CONFIG)
132
+ @line_count = @config[:page_height]
133
+ end
134
+
135
+ def save_config cfg = @config
136
+ File.open(CONFIG, 'w') { |f| f.write cfg.to_yaml}
137
+ end
138
+
139
+ def rss_addresses
140
+ host = 'http://www.bbc.co.uk/programmes'
141
+ [ "/b006qykl/episodes/downloads.rss",
142
+ "/p01drwny/episodes/downloads.rss",
143
+ "/p01dh5yg/episodes/downloads.rss",
144
+ "/p01f0vzr/episodes/downloads.rss",
145
+ "/p01gvqlg/episodes/downloads.rss",
146
+ "/p01gyd7j/episodes/downloads.rss"
147
+ ].collect{|page| host + page}
148
+ end
149
+
150
+ def local_rss
151
+ [
152
+ "culture.rss",
153
+ "history.rss",
154
+ "in_our_time.rss",
155
+ "philosophy.rss",
156
+ "religion.rss",
157
+ "science.rss"
158
+ ]
159
+ end
160
+
161
+ def fetch_uri uri, file
162
+ open(file, "wb") do |f|
163
+ open(uri) do |ur|
164
+ f.write(ur.read)
165
+ end
166
+ end
167
+ end
168
+
169
+ def filename_from_title title
170
+ temp = title.gsub(/[^0-9a-z ]/i, '').gsub(' ', '_').strip + '.mp3'
171
+ File.join(File.join IN_OUR_TIME, AUDIO_DIRECTORY, temp.downcase)
172
+ end
173
+
174
+ def download_audio program, addr
175
+ res = Net::HTTP.get_response(URI.parse(addr))
176
+ case res
177
+ when Net::HTTPOK
178
+ File.open(filename_from_title(program[:title]) , 'wb') do |f|
179
+ iot_print "writing #{filename_from_title(program[:title])}...", :yellow
180
+ f.print(res.body)
181
+ iot_puts " written.", :yellow
182
+ end
183
+ program[:have_locally] = true
184
+ else
185
+ iot_puts 'audio download failed. Retrying...', :yellow
186
+ end
187
+ end
188
+
189
+ def have_locally? title
190
+ filename = filename_from_title(title)
191
+ if File.exists?(filename)
192
+ return true
193
+ end
194
+ false
195
+ end
196
+
197
+ def rss_files
198
+ local_rss.map{|f| File.join IN_OUR_TIME, RSS_DIRECTORY, f }
199
+ end
200
+
201
+ def check_remote
202
+ if update_remote?
203
+ iot_print "checking rss feeds ", :yellow
204
+ local_rss.length.times do |count|
205
+ print '.'
206
+ fetch_uri rss_addresses[count], rss_files[count]
207
+ end
208
+ iot_puts ''
209
+ @config[:last_update] = now
210
+ save_config
211
+ end
212
+ end
213
+
214
+ def uniquify_programs
215
+ @programs = @programs.uniq{|pr| pr[:title]}
216
+ unless @programs.uniq.length == @programs.length
217
+ iot_puts "Error ensuring Programs unique!", :red
218
+ exit 1
219
+ end
220
+ end
221
+
222
+ def parse_rss
223
+ rss_files.each do |file|
224
+ @doc = Nokogiri::XML(File.open(file))
225
+ titles = @doc.xpath("//item//title")
226
+ descs = @doc.xpath("//item//description")
227
+ subtitles = @doc.xpath("//item//itunes:subtitle")
228
+ summarys = @doc.xpath("//item//itunes:summary")
229
+ durations = @doc.xpath("//item//itunes:duration")
230
+ dates = @doc.xpath("//item//pubDate")
231
+ links = @doc.xpath("//item//link")
232
+
233
+ 0.upto (titles.length - 1) do |idx|
234
+ program = {}
235
+ program[:title] = titles[idx].text
236
+ # program[:description] = descs[idx]
237
+ program[:subtitle] = subtitles[idx].text
238
+ program[:summary] = summarys[idx].text
239
+ program[:duration] = durations[idx].text
240
+ program[:date] = (dates[idx].text)[0..15]
241
+ program[:link] = links[idx].text
242
+ program[:have_locally] = have_locally?(titles[idx].text)
243
+ @programs << program
244
+ end
245
+ end
246
+ uniquify_programs
247
+ end
248
+
249
+ def select_program title
250
+ @programs.each do |pr|
251
+ if pr[:title].strip == title.strip
252
+ return pr
253
+ end
254
+ end
255
+ nil
256
+ end
257
+
258
+ def sort_titles
259
+ @sorted_titles = []
260
+ @sorted_titles = @programs.collect { |pr| pr[:title] }
261
+ # @sorted_titles = @sorted_titles.uniq{|x| x.downcase}
262
+ @sorted_titles = @sorted_titles.sort unless @config[:sort] == :age
263
+ end
264
+
265
+ def date
266
+ @programs.map {|pr| return pr[:date] if pr[:title] == @playing}
267
+ end
268
+
269
+ def pre_delay
270
+ x = DateTime.strptime("Mon, 20 Jun 2016", '%a, %d %b %Y')
271
+ y = DateTime.strptime(date, '%a, %d %b %Y')
272
+ y < x ? '410' : '435'
273
+ end
274
+
275
+ def player_cmd
276
+ case @config[:mpg_player]
277
+ when :mpg123
278
+ "mpg123 -qk#{pre_delay}"
279
+ else
280
+ "afplay"
281
+ end
282
+ end
283
+
284
+ def kill_cmd
285
+ "killall " +
286
+ case @config[:mpg_player]
287
+ when :mpg123
288
+ "mpg123"
289
+ else
290
+ "afplay"
291
+ end
292
+ end
293
+
294
+ def run_program prg
295
+ unless prg[:have_locally]
296
+ retries = 0
297
+ iot_puts "fetching #{prg[:title]}", :yellow
298
+ 10.times do
299
+ res = Net::HTTP.get_response(URI.parse(prg[:link]))
300
+ case res
301
+ when Net::HTTPFound
302
+ iot_puts 'redirecting...', :yellow
303
+ @doc = Nokogiri::XML(res.body)
304
+ redirect = @doc.css("body p a").text
305
+ break if download_audio(prg, redirect)
306
+ sleep 2
307
+ else
308
+ iot_puts 'Error! Expected to be redirected!', :red
309
+ exit 1
310
+ end
311
+ retries += 1
312
+ end
313
+ if retries >= 10
314
+ iot_puts "Max retries downloading #{prg[:title]}", :red
315
+ exit 1
316
+ end
317
+ end
318
+ @play = Thread.new do
319
+ @playing = prg[:title]
320
+ system player_cmd + ' ' +
321
+ filename_from_title(@playing)
322
+ @playing = nil
323
+ end
324
+ end
325
+
326
+ def print_playing_maybe
327
+ iot_puts ''
328
+ if @playing
329
+ iot_puts "Playing '#{@playing}'"
330
+ elsif @started.nil?
331
+ @started = true
332
+ iot_puts "? or h for instructions"
333
+ else
334
+ iot_puts ''
335
+ end
336
+ end
337
+
338
+ def kill_audio
339
+ if @playing
340
+ system kill_cmd if @play
341
+ @play.kill if @play
342
+ @playing = nil
343
+ end
344
+ end
345
+
346
+ def idx_format idx
347
+ sprintf("%03d, ", idx + 1)
348
+ end
349
+
350
+ def show_count_maybe idx
351
+ if have_locally?(@sorted_titles[idx])
352
+ iot_print idx_format(idx), :cyan if @config[:show_count]
353
+ else
354
+ iot_print idx_format(idx), :yellow if @config[:show_count]
355
+ end
356
+ end
357
+
358
+ def draw_page
359
+ if @line_count <= @sorted_titles.length
360
+ @line_count.upto(@line_count + @config[:page_height] - 1) do |idx|
361
+ if idx < @sorted_titles.length
362
+ iot_print "> " if(idx == @selected) unless @config[:colour]
363
+ show_count_maybe idx
364
+ iot_puts @sorted_titles[idx], :purple if (idx == @selected)
365
+ iot_puts @sorted_titles[idx], :default unless(idx == @selected)
366
+ end
367
+ end
368
+ else
369
+ @line_count = 0
370
+ 0.upto(@config[:page_height] - 1) do |idx|
371
+ iot_print "> " if(idx == @selected)
372
+ show_count_maybe(idx) unless @sorted_titles[idx].nil?
373
+ iot_puts @sorted_titles[idx] unless @sorted_titles[idx].nil?
374
+ end
375
+ end
376
+ @line_count += @config[:page_height]
377
+ print_playing_maybe
378
+ end
379
+
380
+ def display_list action
381
+ system 'clear'
382
+ case action
383
+ when :draw_page
384
+ draw_page
385
+ when :previous_page
386
+ if @line_count > 0
387
+ @line_count -= (@config[:page_height] * 2)
388
+ else
389
+ @line_count = @sorted_titles.length
390
+ @selected = @line_count
391
+ end
392
+ draw_page
393
+ when :same_page
394
+ @line_count -= @config[:page_height]
395
+ draw_page
396
+ end
397
+ end
398
+
399
+ def help
400
+ unless @help
401
+ system 'clear'
402
+ iot_puts ''
403
+ iot_puts " In Our Time Player (Help) "
404
+ iot_puts ''
405
+ iot_puts " Next - N (down arrow) "
406
+ iot_puts " Previous - P (up arrow) "
407
+ iot_puts " Next Page - (right arrow) "
408
+ iot_puts " Next Page - (space) "
409
+ iot_puts " Play - X (return) "
410
+ iot_puts " Stop - S "
411
+ iot_puts " List - L "
412
+ iot_puts " Info - I "
413
+ iot_puts " Help - H "
414
+ iot_puts " Quit - Q "
415
+ iot_puts ''
416
+ iot_puts " tl;dr: "
417
+ iot_puts ''
418
+ iot_puts " Select: up/down arrows "
419
+ iot_puts " Play: enter "
420
+ 18.upto(@config[:page_height] - 1) {iot_puts}
421
+ print_playing_maybe
422
+ @help = true
423
+ else
424
+ display_list :same_page
425
+ @help = nil
426
+ end
427
+ end
428
+
429
+ def reformat info
430
+ info.gsub('With ', "\nWith ")
431
+ .gsub('With: ', "\nWith: ")
432
+ .gsub('Producer', "- Producer")
433
+ end
434
+
435
+ def justify info
436
+ collect, top, bottom = [], 0, @config[:page_width]
437
+ loop do
438
+ if(bottom >= info.length)
439
+ collect << info[top..-1].strip
440
+ break
441
+ end
442
+ loop do
443
+ break unless info[top] == ' '
444
+ top += 1 ; bottom += 1
445
+ end
446
+ loop do
447
+ if idx = info[top..bottom].index("\n")
448
+ collect << info[top..top + idx]
449
+ bottom, top = top + idx + @config[:page_width] + 1, top + idx + 1
450
+ next
451
+ else
452
+ break if (info[bottom] == ' ')
453
+ bottom -= 1
454
+ end
455
+ end
456
+ collect << info[top..bottom]
457
+ bottom, top = bottom + @config[:page_width], bottom
458
+ end
459
+ collect
460
+ end
461
+
462
+ def info
463
+ if @info.nil?
464
+ system 'clear'
465
+ iot_puts ''
466
+ prg = select_program @sorted_titles[@selected]
467
+ iot_puts justify(prg[:subtitle].gsub(/\s+/, ' '))
468
+ iot_puts ''
469
+ iot_puts "Date Broadcast: #{prg[:date]}"
470
+ iot_puts "Duration: #{prg[:duration].to_i/60} mins"
471
+ iot_puts "Availability: " +
472
+ (prg[:have_locally] ? "Downloaded" : "Requires Download")
473
+ @info = 1
474
+ elsif @info == 1
475
+ system 'clear'
476
+ iot_puts ''
477
+ prg = select_program @sorted_titles[@selected]
478
+ info = prg[:summary].gsub(/\s+/, ' ')
479
+ iot_puts justify(reformat(info))
480
+ @info = -1
481
+ else
482
+ display_list :same_page
483
+ @info = nil
484
+ end
485
+ end
486
+
487
+ def run
488
+ display_list :same_page
489
+ key = KeyboardEvents.new
490
+ loop do
491
+ ip = key.input
492
+ @info = nil unless ip == :info
493
+ @help = nil unless ip == :help
494
+
495
+ case ip
496
+ when :list
497
+ @line_count = 0
498
+ @selected = 0
499
+ display_list :draw_page
500
+ when :page_forward
501
+ @selected = @line_count
502
+ display_list :draw_page
503
+ when :previous
504
+ @selected -= 1 if @selected > 0
505
+ if @selected >= @line_count -
506
+ @config[:page_height]
507
+ display_list :same_page
508
+ else
509
+ display_list :previous_page
510
+ end
511
+ when :next
512
+ @selected += 1
513
+ if @selected <= @line_count - 1
514
+ display_list :same_page
515
+ else
516
+ display_list :draw_page
517
+ end
518
+ when :play
519
+ kill_audio
520
+ title = @sorted_titles[@selected]
521
+ pr = select_program title
522
+ run_program pr
523
+ display_list :same_page
524
+ when :stop
525
+ kill_audio
526
+ when :info
527
+ info
528
+ when :help
529
+ help
530
+ when :quit
531
+ kill_audio
532
+ exit 0
533
+ end
534
+ sleep 0.001
535
+ end
536
+ end
537
+ end
538
+
539
+ InOurTime.new if __FILE__ == $0
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: in_our_time
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Martyn Jago
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-09-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.8
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.6.8
27
+ - !ruby/object:Gem::Dependency
28
+ name: version
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.0
41
+ description: In Our Time Player
42
+ email:
43
+ - martyn.jago@btinternet.com
44
+ executables:
45
+ - iot
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - Rakefile
52
+ - VERSION
53
+ - bin/iot
54
+ - in_our_time.gemspec
55
+ - lib/in_our_time.rb
56
+ - lib/iot/colour_prompt.rb
57
+ - lib/iot/iot.rb
58
+ homepage: https://github.com/mjago/In_Our_Time
59
+ licenses:
60
+ - MIT
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 2.0.0
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.6.6
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Select, play, and download BBC 'In Our Time' podcasts - all from the command
82
+ line
83
+ test_files: []