in_our_time 0.3.4 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|