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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2cf2c996c094b425c9b23dfdc1d333be877ad11b
4
- data.tar.gz: 27014f8d06c891f07bcb92db25325718d08affc6
3
+ metadata.gz: fba0bd53285d9df8789fb1d0464650ed0c769a41
4
+ data.tar.gz: e190622c306d519d8d0a568d629c3f06dc1a5a79
5
5
  SHA512:
6
- metadata.gz: c124de122df9bc9ac02db4c35461e48ca010a3d99a806e222ef5ec5108512e2a4ff9b931afc1b741c38a99f4a86dd24f1f4a9e97176792850bacb6bc74db8c67
7
- data.tar.gz: e6b1afc628991379da911fdcd8a4a6cd051859c05f396e085b765658779758d3e35f119d63d47721148caef008fd7c58c01f24f49661690d09ea945586d0e626
6
+ metadata.gz: 5293b5c48c8a45a2dc7efc464f0ce3c87fdffddd9546e7c4223d339335ef4cd400f8c989fd5c4d227ebd1afd1559a5e72abeea28dfce4287ce9036e8045e0e9a
7
+ data.tar.gz: 86738cce5846617abd0f2aac1d019c88eca1a59143792e59c6c7b5137ebcfeaf690fc151ef2334ec9b3d0ebace094170eb1aa381039cc99c96fca7738ce9a239
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  /audio/
2
2
  /rss/
3
3
  /in_our_time.org
4
+ /.rubocop_todo.yml
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.4
1
+ 0.4.0
data/in_our_time.gemspec CHANGED
@@ -24,3 +24,4 @@ Gem::Specification.new do |spec|
24
24
  spec.add_runtime_dependency 'colorize', '>= 0.8.1'
25
25
  spec.add_development_dependency 'version', '>= 1.0.0'
26
26
  end
27
+
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, @flag = @flag, false
46
+ ret_val = @flag
47
+ @flag = false
130
48
  ret_val
131
49
  end
132
50
  end
133
51
 
134
52
  def initialize
135
- @programs, @selected = [], 0
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
- display_version
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
- system("stty -raw echo")
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
- do_events while Time.now - @start_time < 1
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
- STDOUT.print x.colorize col if @config[:colour]
163
- STDOUT.print x unless @config[:colour]
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
- unless Dir.exist? pages
183
- Dir.mkdir pages
184
- local_rss.map{|f| FileUtils.touch(File.join pages, f)}
185
- end
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
- clear
190
- iot_print("Loading ", @system_colour) unless ARGV[0] == '-v' || ARGV[0] == '--version'
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::load_file(DEFAULT_CONFIG)
173
+ @config = YAML.load_file(DEFAULT_CONFIG)
205
174
  save_config
206
175
  end
207
176
 
208
- def do_configs
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
- rows, cols = $stdout.winsize
216
- while(rows % 10 != 0) ; rows -=1 ; end
217
- while(cols % 10 != 0) ; cols -=1 ; end
218
- rows = 10 if rows < 10
219
- cols = 20 if cols < 20
220
- @config[:page_height] = rows if(@config[:page_height] == :auto)
221
- @config[:page_width] = cols if(@config[:page_width] == :auto)
222
- @line_count = @config[:page_height]
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::load_file(CONFIG)
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, '').gsub(' ', '_').strip + '.mp3'
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 program, addr
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.exists?(filename) ? true : false
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
- clear
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
- unless @programs.uniq.length == @programs.length
314
- print_error_and_delay "Error ensuring Programs unique!"
315
- quit 1
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 (titles.length - 1) do |idx|
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 % @config[:page_height] != 0
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 sort
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 'clear' or system 'cls'
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 2
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
- clear
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, @playing, @paused = nil, nil, nil
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
- if control_play?
475
- @paused = @paused ? false : true
476
- write_player " "
477
- redraw
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("\nPlaying: ", @count_colour) unless @paused
496
- iot_print("\nPaused: ", @count_colour) if @paused
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
- iot_puts "\n? or h for instructions", @text_colour
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
- if @playing
513
- if @pid.is_a? Fixnum
514
- Process.kill('QUIT', @pid)
515
- sleep 0.2
516
- reset
517
- end
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 if @config[:show_count]
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 + @config[:page_height] - 1) do |idx|
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(@config[:page_height] - 1) do |idx|
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 += @config[:page_height]
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 -= (@config[:page_height] * 2)
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 -= @config[:page_height]
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
- if ARGV[0] == '-h' || ARGV[0] == '--help' || ARGV[0] == '-?'
577
- help
578
- quit
579
- end
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
- clear
585
- iot_puts " In Our Time Player (#{@version})"
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 < @config[:page_width]
699
+ info[top..-1].length < @page_width
633
700
  end
634
701
 
635
702
  def justify info
636
703
  pages = [[],[]]
637
- page, top, bottom = 0, 0, @config[:page_width]
704
+ page = 0
705
+ top = 0
706
+ bottom = @page_width
638
707
  loop do
639
708
  shift = top_space info[top..bottom]
640
- top, bottom = top + shift, bottom + shift
709
+ top = top + shift
710
+ bottom = bottom + shift
641
711
  loop do
642
- if idx = info[top..bottom].index("\n")
712
+ idx = info[top..bottom].index("\n")
713
+ if idx
643
714
  pages[page] << info[top..top + idx]
644
- page,bottom,top = 1,top + idx + @config[:page_width] + 1, top + idx + 1
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
- bottom, top = bottom + @config[:page_width], bottom
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) * @config[:page_height]) &&
681
- (count <= @page_count * @config[:page_height])
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 * @config[:page_height] + 1
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?(Fixnum))
795
+ if(@playing && @pid.is_a?(Integer))
719
796
  begin
720
797
  write_player( "\e")
721
- if @pid.is_a? Fixnum
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 run
733
- ip, action = '', :unknown
734
- @tic, @key = Tic.new, KeyboardEvents.new
735
- @tic.run
736
- @key.run
809
+ def page_forward
810
+ @selected = @line_count
811
+ display_list :next_page
812
+ end
737
813
 
738
- redraw
739
- loop do
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
- unless action == :unknown
742
- @key.reset
743
- end
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
- @info = nil unless ip == :info
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.3.4
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-10-27 00:00:00.000000000 Z
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.6.7
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