in_our_time 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []