in_our_time 0.3.4 → 0.4.0
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 +4 -4
- data/.gitignore +1 -0
- data/VERSION +1 -1
- data/in_our_time.gemspec +1 -0
- data/lib/iot/iot.rb +349 -269
- data/lib/iot/keyboard_events.rb +102 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fba0bd53285d9df8789fb1d0464650ed0c769a41
|
4
|
+
data.tar.gz: e190622c306d519d8d0a568d629c3f06dc1a5a79
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5293b5c48c8a45a2dc7efc464f0ce3c87fdffddd9546e7c4223d339335ef4cd400f8c989fd5c4d227ebd1afd1559a5e72abeea28dfce4287ce9036e8045e0e9a
|
7
|
+
data.tar.gz: 86738cce5846617abd0f2aac1d019c88eca1a59143792e59c6c7b5137ebcfeaf690fc151ef2334ec9b3d0ebace094170eb1aa381039cc99c96fca7738ce9a239
|
data/.gitignore
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/in_our_time.gemspec
CHANGED
data/lib/iot/iot.rb
CHANGED
@@ -8,9 +8,9 @@ require 'colorize'
|
|
8
8
|
require 'oga'
|
9
9
|
require 'pty'
|
10
10
|
require 'io/console'
|
11
|
+
require_relative 'keyboard_events'
|
11
12
|
|
12
13
|
class InOurTime
|
13
|
-
|
14
14
|
ROOT = File.expand_path '~/'
|
15
15
|
HERE = File.dirname(__FILE__)
|
16
16
|
CONFIG_DIR = '.in_our_time'
|
@@ -22,102 +22,19 @@ class InOurTime
|
|
22
22
|
UPDATE_INTERVAL = 604800
|
23
23
|
AUDIO_DIRECTORY = 'audio'
|
24
24
|
RSS_DIRECTORY = 'rss'
|
25
|
-
PAGE_HEIGHT = 20
|
26
|
-
PAGE_WIDTH = 80
|
27
|
-
|
28
|
-
class KeyboardEvents
|
29
|
-
|
30
|
-
def initialize
|
31
|
-
@mode = :normal
|
32
|
-
@event = :no_event
|
33
|
-
end
|
34
|
-
|
35
|
-
def reset
|
36
|
-
STDIN.flush
|
37
|
-
end
|
38
|
-
|
39
|
-
def ke_events
|
40
|
-
sleep 0.001
|
41
|
-
end
|
42
|
-
|
43
|
-
def read
|
44
|
-
ret_val = @event
|
45
|
-
# reset
|
46
|
-
@event = :no_event
|
47
|
-
ret_val
|
48
|
-
end
|
49
|
-
|
50
|
-
def run
|
51
|
-
Thread.new do
|
52
|
-
loop do
|
53
|
-
str = ''
|
54
|
-
loop do
|
55
|
-
str = STDIN.getch
|
56
|
-
if str == "\e"
|
57
|
-
@mode = :escape
|
58
|
-
else
|
59
|
-
case @mode
|
60
|
-
when :escape
|
61
|
-
if str == "["
|
62
|
-
@mode = :escape_2
|
63
|
-
else
|
64
|
-
@mode = :normal
|
65
|
-
end
|
66
|
-
when :escape_2
|
67
|
-
@event = :previous if str == "A"
|
68
|
-
@event = :next if str == "B"
|
69
|
-
@event = :page_forward if str == "C"
|
70
|
-
@event = :previous if str == "D"
|
71
|
-
@mode = :normal
|
72
|
-
|
73
|
-
else
|
74
|
-
break if @event == :no_event
|
75
|
-
end
|
76
|
-
end
|
77
|
-
ke_events
|
78
|
-
end
|
79
|
-
|
80
|
-
case str
|
81
|
-
when "\e"
|
82
|
-
@mode = :escape
|
83
|
-
when "l",'L'
|
84
|
-
@event = :list
|
85
|
-
when "u",'U'
|
86
|
-
@event = :update
|
87
|
-
when ' '
|
88
|
-
@event = :page_forward
|
89
|
-
when "q",'Q', "\u0003", "\u0004"
|
90
|
-
@event = :quit
|
91
|
-
when 'p', 'P'
|
92
|
-
@event = :pause
|
93
|
-
when 'f', 'F'
|
94
|
-
@event = :forward
|
95
|
-
when 'r', 'R'
|
96
|
-
@event = :rewind
|
97
|
-
when 's', 'S'
|
98
|
-
@event = :sort
|
99
|
-
when 'x', 'X', "\r"
|
100
|
-
@event = :play
|
101
|
-
when 'i', 'I'
|
102
|
-
@event = :info
|
103
|
-
when '?', 'h'
|
104
|
-
@event = :help
|
105
|
-
else
|
106
|
-
@event = :no_event
|
107
|
-
end
|
108
|
-
ke_events
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
25
|
|
114
26
|
class Tic
|
115
27
|
def initialize
|
116
28
|
@flag = false
|
29
|
+
run
|
30
|
+
end
|
31
|
+
|
32
|
+
def kill
|
33
|
+
Thread.kill(@th_tic) if @th_tic
|
117
34
|
end
|
118
35
|
|
119
36
|
def run
|
120
|
-
Thread.new do
|
37
|
+
@th_tic = Thread.new do
|
121
38
|
loop do
|
122
39
|
sleep 1
|
123
40
|
@flag = true
|
@@ -126,41 +43,56 @@ class InOurTime
|
|
126
43
|
end
|
127
44
|
|
128
45
|
def toc
|
129
|
-
ret_val
|
46
|
+
ret_val = @flag
|
47
|
+
@flag = false
|
130
48
|
ret_val
|
131
49
|
end
|
132
50
|
end
|
133
51
|
|
134
52
|
def initialize
|
135
|
-
@
|
53
|
+
@content = ''
|
54
|
+
@programs = []
|
55
|
+
@selected = 0
|
56
|
+
clear
|
57
|
+
print "\e[?25h"
|
136
58
|
setup
|
137
59
|
load_config
|
138
60
|
load_version
|
139
61
|
load_help_maybe
|
140
|
-
|
62
|
+
opening_title
|
141
63
|
check_remote
|
142
64
|
parse_rss
|
143
65
|
sort_titles
|
144
66
|
version_display_wait
|
67
|
+
STDIN.echo = false
|
68
|
+
STDIN.raw!
|
145
69
|
run
|
146
70
|
end
|
147
71
|
|
148
72
|
def do_events
|
149
73
|
sleep 0.003
|
74
|
+
sleep 0.1
|
150
75
|
end
|
151
76
|
|
152
77
|
def quit code = 0
|
153
|
-
|
78
|
+
STDIN.echo = true
|
79
|
+
STDIN.cooked!
|
80
|
+
clear
|
81
|
+
puts 'Quitting...'
|
82
|
+
clear
|
83
|
+
@key.kill
|
84
|
+
@tic.kill
|
154
85
|
exit code
|
155
86
|
end
|
156
87
|
|
157
88
|
def version_display_wait
|
158
|
-
|
89
|
+
return if dev_mode?
|
90
|
+
do_events while Time.now - @start_time < 1.5
|
159
91
|
end
|
160
92
|
|
161
93
|
def iot_print x, col = @text_colour
|
162
|
-
|
163
|
-
|
94
|
+
@content << x.colorize(col) if @config[:colour]
|
95
|
+
@content << x unless @config[:colour]
|
164
96
|
end
|
165
97
|
|
166
98
|
def iot_puts x = '', col = @text_colour
|
@@ -168,6 +100,15 @@ class InOurTime
|
|
168
100
|
iot_print "\n\r"
|
169
101
|
end
|
170
102
|
|
103
|
+
def clear_content
|
104
|
+
@content.clear
|
105
|
+
end
|
106
|
+
|
107
|
+
def render
|
108
|
+
clear
|
109
|
+
$stdout << @content
|
110
|
+
end
|
111
|
+
|
171
112
|
def now
|
172
113
|
Time.now.to_i
|
173
114
|
end
|
@@ -179,16 +120,44 @@ class InOurTime
|
|
179
120
|
pages = File.join iot, RSS_DIRECTORY
|
180
121
|
Dir.mkdir iot unless Dir.exist? iot
|
181
122
|
Dir.mkdir audio unless Dir.exist? audio
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
123
|
+
return if Dir.exist?(pages)
|
124
|
+
Dir.mkdir pages
|
125
|
+
local_rss.map{|f| FileUtils.touch(File.join pages, f)}
|
126
|
+
end
|
127
|
+
|
128
|
+
def dev_mode?
|
129
|
+
ENV['IN_OUR_TIME'] == 'development'
|
130
|
+
end
|
131
|
+
|
132
|
+
def puts_title colour
|
133
|
+
title =
|
134
|
+
%q{ _____ ____ _______ _
|
135
|
+
|_ _| / __ \ |__ __(_)
|
136
|
+
| | _ __ | | | |_ _ _ __ | | _ _ __ ___ ___
|
137
|
+
| | | '_ \ | | | | | | | '__| | | | | '_ ` _ \ / _ \
|
138
|
+
_| |_| | | | | |__| | |_| | | | | | | | | | | | __/
|
139
|
+
|_____|_| |_| \____/ \__,_|_| |_| |_|_| |_| |_|\___|
|
140
|
+
}
|
141
|
+
|
142
|
+
title.split("\n").map{|l| iot_print(l + "\r\n", colour)} if(window_width > 61)
|
143
|
+
iot_puts("In Our Time\r", colour) unless(window_width > 61)
|
144
|
+
iot_puts
|
145
|
+
end
|
146
|
+
|
147
|
+
def opening_title
|
148
|
+
return if dev_mode?
|
149
|
+
puts_title :light_green
|
150
|
+
render
|
151
|
+
sleep 0.5
|
152
|
+
clear_content
|
153
|
+
puts_title @system_colour
|
154
|
+
display_version
|
155
|
+
render
|
186
156
|
end
|
187
157
|
|
188
158
|
def display_version
|
189
|
-
|
190
|
-
|
191
|
-
iot_puts "In Our Time Player (#{@version})", @system_colour
|
159
|
+
iot_print("Loading ", :light_green) unless ARGV[0] == '-v' || ARGV[0] == '--version'
|
160
|
+
iot_puts "In Our Time Player (#{@version})", :light_green
|
192
161
|
quit if ARGV[0] == '-v' || ARGV[0] == '--version'
|
193
162
|
end
|
194
163
|
|
@@ -201,31 +170,71 @@ class InOurTime
|
|
201
170
|
end
|
202
171
|
|
203
172
|
def create_config
|
204
|
-
@config = YAML
|
173
|
+
@config = YAML.load_file(DEFAULT_CONFIG)
|
205
174
|
save_config
|
206
175
|
end
|
207
176
|
|
208
|
-
def
|
177
|
+
def init_theme
|
209
178
|
theme = @config[:colour_theme]
|
210
179
|
@selection_colour = @config[theme][:selection_colour]
|
211
180
|
@count_sel_colour = @config[theme][:count_sel_colour]
|
212
181
|
@count_colour = @config[theme][:count_colour]
|
213
182
|
@text_colour = @config[theme][:text_colour]
|
214
183
|
@system_colour = @config[theme][:system_colour]
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
184
|
+
end
|
185
|
+
|
186
|
+
def theme_toggle
|
187
|
+
theme = @config[:colour_theme]
|
188
|
+
@config[:colour_theme] = theme == :light_theme ?
|
189
|
+
:dark_theme : :light_theme
|
190
|
+
save_config
|
191
|
+
init_theme
|
192
|
+
redraw
|
193
|
+
end
|
194
|
+
|
195
|
+
def set_height
|
196
|
+
height = window_height
|
197
|
+
while(height -2 % 10 != 0) ; height -=1 ; end
|
198
|
+
height = 10 if height < 10
|
199
|
+
@page_height = height if(@config[:page_height] == :auto)
|
200
|
+
@page_height = @config[:page_height] unless(@config[:page_height] == :auto)
|
201
|
+
end
|
202
|
+
|
203
|
+
def set_width
|
204
|
+
width = window_width
|
205
|
+
while(width % 10 != 0) ; width -=1 ; end
|
206
|
+
width = 20 if width < 20
|
207
|
+
@page_width = width - 1 if(@config[:page_width] == :auto)
|
208
|
+
@page_width = @config[:page_width] unless(@config[:page_width] == :auto)
|
209
|
+
end
|
210
|
+
|
211
|
+
def window_height
|
212
|
+
$stdout.winsize.first
|
213
|
+
end
|
214
|
+
|
215
|
+
def window_width
|
216
|
+
$stdout.winsize[1]
|
217
|
+
end
|
218
|
+
|
219
|
+
def set_dimensions
|
220
|
+
set_height
|
221
|
+
set_width
|
222
|
+
end
|
223
|
+
|
224
|
+
def init_line_count
|
225
|
+
@line_count = @page_height
|
226
|
+
end
|
227
|
+
|
228
|
+
def do_configs
|
229
|
+
init_theme
|
230
|
+
set_dimensions
|
231
|
+
init_line_count
|
223
232
|
@sort = @config[:sort]
|
224
233
|
end
|
225
234
|
|
226
235
|
def load_config
|
227
236
|
create_config unless File.exist? CONFIG
|
228
|
-
@config = YAML
|
237
|
+
@config = YAML.load_file(CONFIG)
|
229
238
|
do_configs
|
230
239
|
end
|
231
240
|
|
@@ -264,28 +273,32 @@ class InOurTime
|
|
264
273
|
end
|
265
274
|
|
266
275
|
def filename_from_title title
|
267
|
-
temp = title.gsub(/[^0-9a-z ]/i, '').
|
276
|
+
temp = title.gsub(/[^0-9a-z ]/i, '').tr(' ', '_').strip + '.mp3'
|
268
277
|
File.join IN_OUR_TIME, AUDIO_DIRECTORY, temp.downcase
|
269
278
|
end
|
270
279
|
|
271
|
-
def download_audio
|
280
|
+
def download_audio(program, addr)
|
272
281
|
res = Net::HTTP.get_response(URI.parse(addr))
|
273
282
|
case res
|
274
283
|
when Net::HTTPOK
|
275
284
|
File.open(filename_from_title(program[:title]) , 'wb') do |f|
|
276
285
|
iot_print "writing #{filename_from_title(program[:title])}...", @system_colour
|
286
|
+
render
|
277
287
|
f.print(res.body)
|
278
288
|
iot_puts " written.", @system_colour
|
289
|
+
render
|
279
290
|
end
|
280
291
|
program[:have_locally] = true
|
281
292
|
else
|
282
293
|
iot_puts 'Download failed. Retrying...', @system_colour
|
294
|
+
render
|
295
|
+
nil
|
283
296
|
end
|
284
297
|
end
|
285
298
|
|
286
299
|
def have_locally? title
|
287
300
|
filename = filename_from_title(title)
|
288
|
-
File.
|
301
|
+
File.exist?(filename) ? true : false
|
289
302
|
end
|
290
303
|
|
291
304
|
def rss_files
|
@@ -293,13 +306,14 @@ class InOurTime
|
|
293
306
|
end
|
294
307
|
|
295
308
|
def update
|
296
|
-
|
309
|
+
clear_content
|
297
310
|
iot_print "Checking rss feeds ", @system_colour
|
298
311
|
local_rss.length.times do |count|
|
299
312
|
iot_print '.', @system_colour
|
313
|
+
render
|
300
314
|
fetch_uri rss_addresses[count], rss_files[count]
|
301
315
|
end
|
302
|
-
iot_puts
|
316
|
+
# iot_puts
|
303
317
|
@config[:last_update] = now
|
304
318
|
save_config
|
305
319
|
end
|
@@ -310,10 +324,9 @@ class InOurTime
|
|
310
324
|
|
311
325
|
def uniquify_programs
|
312
326
|
@programs = @programs.uniq{|pr| pr[:title]}
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
end
|
327
|
+
return if @programs.uniq.length == @programs.length
|
328
|
+
print_error_and_delay "Error ensuring Programs unique!"
|
329
|
+
quit 1
|
317
330
|
end
|
318
331
|
|
319
332
|
def parse_rss
|
@@ -326,7 +339,7 @@ class InOurTime
|
|
326
339
|
dates = @doc.xpath('rss/channel/item/pubDate')
|
327
340
|
links = @doc.xpath('rss/channel/item/link')
|
328
341
|
|
329
|
-
0.upto
|
342
|
+
0.upto(titles.length - 1) do |idx|
|
330
343
|
program = {}
|
331
344
|
program[:title] = titles[idx].text
|
332
345
|
program[:subtitle] = subtitles[idx].text
|
@@ -357,7 +370,7 @@ class InOurTime
|
|
357
370
|
if st == title
|
358
371
|
selected = idx
|
359
372
|
idx += 1
|
360
|
-
while idx % @
|
373
|
+
while idx % @page_height != 0
|
361
374
|
idx += 1
|
362
375
|
end
|
363
376
|
return selected, idx
|
@@ -365,12 +378,55 @@ class InOurTime
|
|
365
378
|
end
|
366
379
|
end
|
367
380
|
|
368
|
-
def
|
381
|
+
def list_selected title
|
382
|
+
@selected, @line_count = sort_selected(title)
|
383
|
+
redraw
|
384
|
+
end
|
385
|
+
|
386
|
+
def list_playing
|
387
|
+
title = @sorted_titles[@selected]
|
388
|
+
if title == @playing
|
389
|
+
list_top
|
390
|
+
else
|
391
|
+
list_selected @playing
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
def list_stopped
|
396
|
+
if @selected == 0
|
397
|
+
title = @sorted_titles[@last_selected || 0]
|
398
|
+
list_selected title
|
399
|
+
else
|
400
|
+
list_top
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
def list_key
|
405
|
+
if @playing
|
406
|
+
list_playing
|
407
|
+
else
|
408
|
+
list_stopped
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
def list_top
|
413
|
+
@last_selected = @selected
|
414
|
+
@line_count = 0
|
415
|
+
@selected = 0
|
416
|
+
display_list :next_page
|
417
|
+
end
|
418
|
+
|
419
|
+
def sort_key
|
369
420
|
title = @sorted_titles[@selected]
|
421
|
+
toggle_sort
|
422
|
+
list_selected title
|
423
|
+
end
|
424
|
+
|
425
|
+
def toggle_sort
|
370
426
|
@sort = @sort == :age ? :alphabet : :age
|
427
|
+
@config[:sort] = @sort
|
428
|
+
save_config
|
371
429
|
sort_titles
|
372
|
-
@selected, @line_count = sort_selected(title)
|
373
|
-
redraw
|
374
430
|
end
|
375
431
|
|
376
432
|
def redraw
|
@@ -402,43 +458,47 @@ class InOurTime
|
|
402
458
|
end
|
403
459
|
|
404
460
|
def clear
|
405
|
-
system
|
461
|
+
system('clear') || system('cls')
|
406
462
|
end
|
407
463
|
|
408
|
-
def print_error_and_delay message
|
464
|
+
def print_error_and_delay message, delay = 2
|
409
465
|
iot_puts message, :red
|
410
|
-
sleep
|
466
|
+
sleep delay
|
411
467
|
end
|
412
468
|
|
413
469
|
def run_program prg
|
414
470
|
unless prg[:have_locally]
|
415
471
|
retries = 0
|
416
|
-
|
472
|
+
clear_content
|
417
473
|
iot_puts "Fetching #{prg[:title]}", @system_colour
|
474
|
+
render
|
418
475
|
10.times do
|
419
476
|
begin
|
420
477
|
res = Net::HTTP.get_response(URI.parse(prg[:link]))
|
421
478
|
rescue SocketError => e
|
422
479
|
print_error_and_delay "Error: Failed to connect to Internet! (#{e.class})"
|
480
|
+
render
|
423
481
|
@no_play = true
|
424
482
|
break
|
425
483
|
end
|
426
484
|
case res
|
427
485
|
when Net::HTTPFound
|
428
486
|
iot_puts 'redirecting...', @system_colour
|
487
|
+
render
|
429
488
|
@doc = Oga.parse_xml(res.body)
|
430
489
|
redirect = @doc.css("body p a").text
|
431
490
|
break if download_audio(prg, redirect)
|
432
491
|
sleep 2
|
433
492
|
else
|
434
493
|
print_error_and_delay 'Error! Failed to be redirected!'
|
494
|
+
render
|
435
495
|
@no_play = true
|
436
|
-
break
|
437
496
|
end
|
438
497
|
retries += 1
|
439
498
|
end
|
440
499
|
if retries >= 10
|
441
500
|
print_error_and_delay "Max retries downloading #{prg[:title]}"
|
501
|
+
render
|
442
502
|
@no_play = true
|
443
503
|
end
|
444
504
|
end
|
@@ -457,7 +517,9 @@ class InOurTime
|
|
457
517
|
end
|
458
518
|
|
459
519
|
def reset
|
460
|
-
@pid
|
520
|
+
@pid = nil
|
521
|
+
@playing = nil
|
522
|
+
@paused = nil
|
461
523
|
window_title
|
462
524
|
redraw
|
463
525
|
end
|
@@ -471,11 +533,10 @@ class InOurTime
|
|
471
533
|
end
|
472
534
|
|
473
535
|
def pause
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
end
|
536
|
+
return unless control_play?
|
537
|
+
@paused = @paused ? false : true
|
538
|
+
write_player " "
|
539
|
+
redraw
|
479
540
|
end
|
480
541
|
|
481
542
|
def control_play?
|
@@ -492,30 +553,22 @@ class InOurTime
|
|
492
553
|
|
493
554
|
def print_playing_maybe
|
494
555
|
if @playing
|
495
|
-
iot_print("
|
496
|
-
iot_print("
|
556
|
+
iot_print("Playing: ", @count_colour) unless @paused
|
557
|
+
iot_print("Paused: ", @count_colour) if @paused
|
497
558
|
iot_puts @playing, @selection_colour
|
498
559
|
elsif @started.nil?
|
499
560
|
@started = true
|
500
|
-
|
501
|
-
else
|
502
|
-
iot_puts "\n"
|
561
|
+
iot_print "? or h for instructions", @text_colour
|
503
562
|
end
|
504
563
|
end
|
505
564
|
|
506
|
-
def kill_cmd
|
507
|
-
"killall " +
|
508
|
-
@config[:mpg_player].to_s
|
509
|
-
end
|
510
|
-
|
511
565
|
def kill_audio
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
end
|
566
|
+
return unless @playing
|
567
|
+
@playing = nil
|
568
|
+
return unless @pid.is_a?(Integer)
|
569
|
+
Process.kill('QUIT', @pid)
|
570
|
+
sleep 0.2
|
571
|
+
reset
|
519
572
|
end
|
520
573
|
|
521
574
|
def idx_format idx
|
@@ -524,7 +577,7 @@ class InOurTime
|
|
524
577
|
|
525
578
|
def show_count_maybe idx
|
526
579
|
if have_locally?(@sorted_titles[idx])
|
527
|
-
iot_print idx_format(idx), @count_sel_colour
|
580
|
+
iot_print idx_format(idx), @count_sel_colour if @config[:show_count]
|
528
581
|
else
|
529
582
|
iot_print idx_format(idx), @count_colour if @config[:show_count]
|
530
583
|
end
|
@@ -532,8 +585,9 @@ class InOurTime
|
|
532
585
|
end
|
533
586
|
|
534
587
|
def draw_page
|
588
|
+
clear_content
|
535
589
|
if @line_count <= @sorted_titles.length
|
536
|
-
@line_count.upto(@line_count + @
|
590
|
+
@line_count.upto(@line_count + @page_height - 1) do |idx|
|
537
591
|
if idx < @sorted_titles.length
|
538
592
|
iot_print "> " if(idx == @selected) unless @config[:colour]
|
539
593
|
show_count_maybe idx
|
@@ -543,65 +597,79 @@ class InOurTime
|
|
543
597
|
end
|
544
598
|
else
|
545
599
|
@line_count = 0
|
546
|
-
0.upto(@
|
600
|
+
0.upto(@page_height - 1) do |idx|
|
547
601
|
iot_print "> ", @selection_colour if(idx == @selected)
|
548
602
|
show_count_maybe(idx) unless @sorted_titles[idx].nil?
|
549
603
|
iot_puts @sorted_titles[idx], @text_colour unless @sorted_titles[idx].nil?
|
550
604
|
end
|
551
605
|
end
|
552
|
-
@line_count += @
|
606
|
+
@line_count += @page_height
|
553
607
|
print_playing_maybe
|
608
|
+
render
|
554
609
|
end
|
555
610
|
|
556
611
|
def display_list action
|
557
|
-
clear
|
558
612
|
case action
|
559
613
|
when :next_page
|
560
614
|
draw_page
|
561
615
|
when :previous_page
|
562
616
|
if @line_count > 0
|
563
|
-
@line_count -= (@
|
617
|
+
@line_count -= (@page_height * 2)
|
564
618
|
else
|
565
619
|
@line_count = @sorted_titles.length
|
566
620
|
@selected = @line_count
|
567
621
|
end
|
568
622
|
draw_page
|
569
623
|
when :same_page
|
570
|
-
@line_count -= @
|
624
|
+
@line_count -= @page_height
|
571
625
|
draw_page
|
572
626
|
end
|
573
627
|
end
|
574
628
|
|
629
|
+
def help_option?
|
630
|
+
ARGV[0] == '-h' || ARGV[0] == '--help' || ARGV[0] == '-?'
|
631
|
+
end
|
632
|
+
|
575
633
|
def load_help_maybe
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
634
|
+
return unless help_option?
|
635
|
+
help
|
636
|
+
quit
|
637
|
+
end
|
638
|
+
|
639
|
+
def help_screen
|
640
|
+
[] <<
|
641
|
+
" In Our Time Player (#{@version})" <<
|
642
|
+
" " <<
|
643
|
+
" Play/Stop - X or Enter " <<
|
644
|
+
" Previous/Next - Down / Up " <<
|
645
|
+
" Next Page - SPACE " <<
|
646
|
+
" Sort - S " <<
|
647
|
+
" Theme Toggle - T " <<
|
648
|
+
" List Top - L " <<
|
649
|
+
" Update - U " <<
|
650
|
+
" Info - I " <<
|
651
|
+
" Help - H " <<
|
652
|
+
" Quit - Q " <<
|
653
|
+
" " <<
|
654
|
+
" mpg123 Controls: " <<
|
655
|
+
" Pause/Resume - P " <<
|
656
|
+
" Forward Skip - F " <<
|
657
|
+
" Reverse Skip - R " <<
|
658
|
+
" " <<
|
659
|
+
"Config: #{CONFIG} "
|
660
|
+
end
|
661
|
+
|
662
|
+
def print_help
|
663
|
+
iot_puts help_screen.map{|x|x.rstrip}.join("\n\r"), @system_colour
|
580
664
|
end
|
581
665
|
|
582
666
|
def help
|
583
667
|
unless @help
|
584
|
-
|
585
|
-
|
586
|
-
iot_puts " Next - N or Down Key ", @system_colour
|
587
|
-
iot_puts " Previous - P or Up Key ", @system_colour
|
588
|
-
iot_puts " Next Page - SPACE ", @system_colour
|
589
|
-
iot_puts " Play/Stop - X or Enter ", @system_colour
|
590
|
-
iot_puts " Sort - S ", @system_colour
|
591
|
-
iot_puts " List Top - L ", @system_colour
|
592
|
-
iot_puts " Update - U ", @system_colour
|
593
|
-
iot_puts " Info - I ", @system_colour
|
594
|
-
iot_puts " Help - H ", @system_colour
|
595
|
-
iot_puts " Quit - Q ", @system_colour
|
596
|
-
iot_puts
|
597
|
-
iot_puts " mpg123 Controls: ", @system_colour
|
598
|
-
iot_puts " Pause/Resume - P ", @system_colour
|
599
|
-
iot_puts " Forward Skip - F ", @system_colour
|
600
|
-
iot_puts " Reverse Skip - R ", @system_colour
|
601
|
-
iot_puts
|
602
|
-
iot_puts "Config: #{CONFIG}", @system_colour
|
668
|
+
clear_content
|
669
|
+
print_help
|
603
670
|
print_playing_maybe
|
604
671
|
@help = true
|
672
|
+
render
|
605
673
|
else
|
606
674
|
redraw
|
607
675
|
@help = nil
|
@@ -609,8 +677,7 @@ class InOurTime
|
|
609
677
|
end
|
610
678
|
|
611
679
|
def reformat info
|
612
|
-
['With','Guests',
|
613
|
-
'Producer','Contributors'].map do | x|
|
680
|
+
['With','Guests','Producer','Contributors'].map do | x|
|
614
681
|
[' ', ':'].map do |y|
|
615
682
|
[x, x.upcase].map do |z|
|
616
683
|
info.gsub!(z + y, "\n" + z + y)
|
@@ -629,19 +696,25 @@ class InOurTime
|
|
629
696
|
end
|
630
697
|
|
631
698
|
def last_line? info, top
|
632
|
-
info[top..-1].length < @
|
699
|
+
info[top..-1].length < @page_width
|
633
700
|
end
|
634
701
|
|
635
702
|
def justify info
|
636
703
|
pages = [[],[]]
|
637
|
-
page
|
704
|
+
page = 0
|
705
|
+
top = 0
|
706
|
+
bottom = @page_width
|
638
707
|
loop do
|
639
708
|
shift = top_space info[top..bottom]
|
640
|
-
top
|
709
|
+
top = top + shift
|
710
|
+
bottom = bottom + shift
|
641
711
|
loop do
|
642
|
-
|
712
|
+
idx = info[top..bottom].index("\n")
|
713
|
+
if idx
|
643
714
|
pages[page] << info[top..top + idx]
|
644
|
-
page
|
715
|
+
page = 1
|
716
|
+
bottom = top + idx + @page_width + 1
|
717
|
+
top = top + idx + 1
|
645
718
|
else
|
646
719
|
break if bottom_space? info[bottom]
|
647
720
|
bottom -= 1
|
@@ -652,13 +725,15 @@ class InOurTime
|
|
652
725
|
break
|
653
726
|
end
|
654
727
|
pages[page] << info[top..bottom]
|
655
|
-
|
728
|
+
top = bottom
|
729
|
+
bottom = bottom + @page_width
|
656
730
|
end
|
657
731
|
pages
|
658
732
|
end
|
659
733
|
|
660
734
|
def print_subtitle prg
|
661
735
|
clear
|
736
|
+
puts_title @system_colour
|
662
737
|
justify(prg[:subtitle].gsub(/\s+/, ' '))[0].map{|x| iot_puts x}
|
663
738
|
print_program_details prg
|
664
739
|
@info = 1
|
@@ -674,16 +749,15 @@ class InOurTime
|
|
674
749
|
|
675
750
|
def print_info prg
|
676
751
|
info = prg[:summary].gsub(/\s+/, ' ')
|
677
|
-
clear
|
678
752
|
count = 1
|
679
753
|
justify(reformat(info))[0].each do |x|
|
680
|
-
if (count > (@page_count - 1) * @
|
681
|
-
(count <= @page_count * @
|
754
|
+
if (count > (@page_count - 1) * @page_height) &&
|
755
|
+
(count <= @page_count * @page_height)
|
682
756
|
iot_puts x
|
683
757
|
end
|
684
758
|
count += 1
|
685
759
|
end
|
686
|
-
if count <= @page_count * @
|
760
|
+
if count <= @page_count * @page_height + 1
|
687
761
|
@info = justify(reformat(info))[1] == [] ? -1 : 2
|
688
762
|
else
|
689
763
|
@page_count += 1
|
@@ -698,6 +772,7 @@ class InOurTime
|
|
698
772
|
end
|
699
773
|
|
700
774
|
def info
|
775
|
+
clear_content
|
701
776
|
case @info
|
702
777
|
when nil
|
703
778
|
prg = select_program @sorted_titles[@selected]
|
@@ -711,14 +786,16 @@ class InOurTime
|
|
711
786
|
else
|
712
787
|
redraw
|
713
788
|
@info = nil
|
789
|
+
return
|
714
790
|
end
|
791
|
+
render
|
715
792
|
end
|
716
793
|
|
717
794
|
def check_process
|
718
|
-
if(@playing && @pid.is_a?(
|
795
|
+
if(@playing && @pid.is_a?(Integer))
|
719
796
|
begin
|
720
797
|
write_player( "\e")
|
721
|
-
if @pid.is_a?
|
798
|
+
if @pid.is_a? Integer
|
722
799
|
Process.kill 0, @pid
|
723
800
|
end
|
724
801
|
rescue Errno::ESRCH
|
@@ -729,83 +806,86 @@ class InOurTime
|
|
729
806
|
end
|
730
807
|
end
|
731
808
|
|
732
|
-
def
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
@key.run
|
809
|
+
def page_forward
|
810
|
+
@selected = @line_count
|
811
|
+
display_list :next_page
|
812
|
+
end
|
737
813
|
|
738
|
-
|
739
|
-
|
814
|
+
def previous
|
815
|
+
@selected -= 1 if @selected > 0
|
816
|
+
if @selected >= @line_count -
|
817
|
+
@page_height
|
818
|
+
redraw
|
819
|
+
else
|
820
|
+
display_list :previous_page
|
821
|
+
end
|
822
|
+
end
|
740
823
|
|
741
|
-
|
742
|
-
|
743
|
-
|
824
|
+
def next
|
825
|
+
@selected += 1
|
826
|
+
if @selected <= @line_count - 1
|
827
|
+
redraw
|
828
|
+
else
|
829
|
+
display_list :next_page
|
830
|
+
end
|
831
|
+
end
|
744
832
|
|
833
|
+
def play
|
834
|
+
if @playing
|
835
|
+
kill_audio
|
836
|
+
else
|
837
|
+
kill_audio
|
838
|
+
title = @sorted_titles[@selected]
|
839
|
+
pr = select_program title
|
840
|
+
run_program pr
|
841
|
+
redraw
|
842
|
+
end
|
843
|
+
end
|
844
|
+
|
845
|
+
def update_key
|
846
|
+
update
|
847
|
+
parse_rss
|
848
|
+
sort_titles
|
849
|
+
@line_count = 0
|
850
|
+
@selected = 0
|
851
|
+
display_list :next_page
|
852
|
+
end
|
853
|
+
|
854
|
+
def quit_key
|
855
|
+
kill_audio
|
856
|
+
quit
|
857
|
+
end
|
858
|
+
|
859
|
+
def do_action ip
|
860
|
+
case ip
|
861
|
+
when :pause, :forward, :rewind,
|
862
|
+
:list_key, :page_forward, :previous,
|
863
|
+
:next, :play, :sort_key, :theme_toggle,
|
864
|
+
:update_key, :info, :help, :quit_key
|
865
|
+
self.send ip
|
866
|
+
end
|
867
|
+
end
|
868
|
+
|
869
|
+
def reset_info_maybe ip
|
870
|
+
@info = nil unless ip == :info
|
871
|
+
@help = nil unless ip == :help
|
872
|
+
end
|
873
|
+
|
874
|
+
def run
|
875
|
+
ip = ''
|
876
|
+
@tic = Tic.new
|
877
|
+
@key = KeyboardEvents.new
|
878
|
+
redraw
|
879
|
+
|
880
|
+
loop do
|
745
881
|
loop do
|
746
882
|
ip = @key.read
|
747
883
|
break unless ip == :no_event
|
748
884
|
check_process if @tic.toc
|
749
885
|
do_events
|
750
886
|
end
|
751
|
-
|
752
|
-
|
753
|
-
@help = nil unless ip == :help
|
754
|
-
|
755
|
-
action =
|
756
|
-
case ip
|
757
|
-
when :pause, :forward, :rewind
|
758
|
-
self.send ip
|
759
|
-
when :list
|
760
|
-
@line_count = 0
|
761
|
-
@selected = 0
|
762
|
-
display_list :next_page
|
763
|
-
when :page_forward
|
764
|
-
@selected = @line_count
|
765
|
-
display_list :next_page
|
766
|
-
when :previous
|
767
|
-
@selected -= 1 if @selected > 0
|
768
|
-
if @selected >= @line_count -
|
769
|
-
@config[:page_height]
|
770
|
-
redraw
|
771
|
-
else
|
772
|
-
display_list :previous_page
|
773
|
-
end
|
774
|
-
when :next
|
775
|
-
@selected += 1
|
776
|
-
if @selected <= @line_count - 1
|
777
|
-
redraw
|
778
|
-
else
|
779
|
-
display_list :next_page
|
780
|
-
end
|
781
|
-
when :play
|
782
|
-
if @playing
|
783
|
-
kill_audio
|
784
|
-
@playing = nil
|
785
|
-
else
|
786
|
-
kill_audio
|
787
|
-
title = @sorted_titles[@selected]
|
788
|
-
pr = select_program title
|
789
|
-
run_program pr
|
790
|
-
redraw
|
791
|
-
end
|
792
|
-
when :sort
|
793
|
-
sort
|
794
|
-
when :update
|
795
|
-
update
|
796
|
-
parse_rss
|
797
|
-
sort_titles
|
798
|
-
@line_count = 0
|
799
|
-
@selected = 0
|
800
|
-
display_list :next_page
|
801
|
-
when :info
|
802
|
-
info
|
803
|
-
when :help
|
804
|
-
help
|
805
|
-
when :quit
|
806
|
-
kill_audio
|
807
|
-
quit
|
808
|
-
end
|
887
|
+
reset_info_maybe ip
|
888
|
+
do_action ip
|
809
889
|
do_events
|
810
890
|
end
|
811
891
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
class KeyboardEvents
|
2
|
+
def initialize
|
3
|
+
update_wait
|
4
|
+
@mode = :normal
|
5
|
+
@event = :no_event
|
6
|
+
@alive = true
|
7
|
+
run
|
8
|
+
end
|
9
|
+
|
10
|
+
def reset
|
11
|
+
STDIN.flush
|
12
|
+
end
|
13
|
+
|
14
|
+
def do_events
|
15
|
+
sleep 0.001
|
16
|
+
end
|
17
|
+
|
18
|
+
def kill
|
19
|
+
@alive = nil
|
20
|
+
Thread.kill(@key) if @key
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_wait
|
24
|
+
@wait = Time.now + 0.02
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset_event
|
28
|
+
@event = :no_event unless @event == :quit_key
|
29
|
+
end
|
30
|
+
|
31
|
+
def read
|
32
|
+
update_wait unless @event == :no_event
|
33
|
+
ret_val = @event
|
34
|
+
reset_event
|
35
|
+
ret_val
|
36
|
+
end
|
37
|
+
|
38
|
+
def run
|
39
|
+
@key = Thread.new do
|
40
|
+
while @event != :quit_key
|
41
|
+
str = ''
|
42
|
+
loop do
|
43
|
+
str = STDIN.getch
|
44
|
+
next if Time.now < @wait
|
45
|
+
if str == "\e"
|
46
|
+
@mode = :escape
|
47
|
+
else
|
48
|
+
case @mode
|
49
|
+
when :escape
|
50
|
+
@mode =
|
51
|
+
str == "[" ? :escape_2 : :normal
|
52
|
+
when :escape_2
|
53
|
+
@event = :previous if str == "A"
|
54
|
+
@event = :next if str == "B"
|
55
|
+
@event = :page_forward if str == "C"
|
56
|
+
@event = :previous if str == "D"
|
57
|
+
@mode = :normal
|
58
|
+
else
|
59
|
+
break if @event == :no_event
|
60
|
+
end
|
61
|
+
end
|
62
|
+
do_events
|
63
|
+
end
|
64
|
+
match_event str
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def match_event str
|
70
|
+
case str
|
71
|
+
when "\e"
|
72
|
+
@mode = :escape
|
73
|
+
when "l",'L'
|
74
|
+
@event = :list_key
|
75
|
+
when "u",'U'
|
76
|
+
@event = :update_key
|
77
|
+
when ' '
|
78
|
+
@event = :page_forward
|
79
|
+
when "q",'Q', "\u0003", "\u0004"
|
80
|
+
@event = :quit_key
|
81
|
+
when 'p', 'P'
|
82
|
+
@event = :pause
|
83
|
+
when 'f', 'F'
|
84
|
+
@event = :forward
|
85
|
+
when 'r', 'R'
|
86
|
+
@event = :rewind
|
87
|
+
when 's', 'S'
|
88
|
+
@event = :sort_key
|
89
|
+
when 't', 'T'
|
90
|
+
@event = :theme_toggle
|
91
|
+
when 'x', 'X', "\r"
|
92
|
+
@event = :play
|
93
|
+
when 'i', 'I'
|
94
|
+
@event = :info
|
95
|
+
when '?', 'h', 'H'
|
96
|
+
@event = :help
|
97
|
+
else
|
98
|
+
return @event = :no_event
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: in_our_time
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martyn Jago
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-11-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oga
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- in_our_time.gemspec
|
73
73
|
- lib/in_our_time.rb
|
74
74
|
- lib/iot/iot.rb
|
75
|
+
- lib/iot/keyboard_events.rb
|
75
76
|
homepage: https://github.com/mjago/In_Our_Time
|
76
77
|
licenses:
|
77
78
|
- MIT
|
@@ -92,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
93
|
version: '0'
|
93
94
|
requirements: []
|
94
95
|
rubyforge_project:
|
95
|
-
rubygems_version: 2.
|
96
|
+
rubygems_version: 2.5.1
|
96
97
|
signing_key:
|
97
98
|
specification_version: 4
|
98
99
|
summary: Select, play, and download BBC 'In Our Time' podcasts - all from the command
|