in_our_time 0.7.0 → 0.7.3

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: 956e4e9773aad8f71897640c04d397bd566f512d
4
- data.tar.gz: 39f0098a0bb42d7f4a16d04fb518f68bfb2fb61a
3
+ metadata.gz: f7366e48fb9235107463e7af22d3b04b30ea7368
4
+ data.tar.gz: 3ef1be69c2de15068ad48ac13ae7bec99f6498bc
5
5
  SHA512:
6
- metadata.gz: 62af2485c95313e901ac884a6eb111a8cc2d407aafa64a1feda55e27c48ac85c1c3183781d4cc0d8c5f672aeeddf11a6bffc693aaafbde34d957e21d04605d30
7
- data.tar.gz: b6bb8e7f15b7f92ce50fe922fc04f418c7058506dbd78b09ce069bd1b8ad77b13a18064dbdf1dbc578df45e379c947f849ae1d294271e28bcd9f0acaa17980cd
6
+ metadata.gz: 30258e410871e24e8f7e8f93d95fd8e8a4464b11d321b5659a8b5f80e79e10091a8c269973d794f084b289f62dda29690d0be8ce8cc8a5d4f1ddaf06d1a85f1d
7
+ data.tar.gz: 3928c59f30aff170246a1480fbc1e0965c0386c115e43f7fc387d9876ed78b9cca85d9e1fae810766a9eef5441a2c9df8dc8b7c54a1370bb8486bdeb219c0fe4
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.7.3
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ require "time"
2
3
  lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
 
@@ -20,7 +21,7 @@ Gem::Specification.new do |spec|
20
21
 
21
22
  spec.require_paths = ["lib"]
22
23
  spec.required_ruby_version = '>= 2.0.0'
23
- spec.add_runtime_dependency 'oga', '~> 2.2'
24
+ spec.add_runtime_dependency 'oga', '>= 2.1.4'
24
25
  spec.add_runtime_dependency 'colorize', '>= 0.8.1'
25
26
  spec.add_development_dependency 'version', '>= 1.0.0'
26
27
  end
@@ -13,30 +13,74 @@ require_relative 'keyboard_events'
13
13
  class InOurTime
14
14
  ROOT = File.expand_path '~/'
15
15
  HERE = File.dirname(__FILE__)
16
- CONFIG_DIR = '.in_our_time'
17
- CONFIG_NAME = 'config.yml'
16
+ CONFIG_DIR = '.in_our_time'.freeze
17
+ CONFIG_NAME = 'config.yml'.freeze
18
18
  IN_OUR_TIME = File.join ROOT, CONFIG_DIR
19
19
  VERSION = File.join HERE, '..','..','VERSION'
20
20
  DEFAULT_CONFIG = File.join HERE, '..','..',CONFIG_NAME
21
21
  CONFIG = File.join IN_OUR_TIME,CONFIG_NAME
22
22
  UPDATE_INTERVAL = 604800
23
- AUDIO_DIRECTORY = 'audio'
24
- RSS_DIRECTORY = 'rss'
23
+ AUDIO_DIRECTORY = '../../../../Volumes/UNTITLED/.in_our_time/audio'.freeze
24
+ # AUDIO_DIRECTORY = 'audio'.freeze
25
+ RSS_DIRECTORY = 'rss'.freeze
25
26
 
26
27
  class Tic
27
28
  def initialize
29
+ Thread.abort_on_exception = true
28
30
  @flag = false
31
+ init_processes
29
32
  run
30
33
  end
31
34
 
35
+ def init_processes
36
+ @processes =
37
+ { process: {
38
+ timeout: 5,
39
+ value: 0 },
40
+ playing_time: {
41
+ timeout: 1,
42
+ value: 0 },
43
+ ended: {
44
+ timeout: 1,
45
+ value: 0 }
46
+ }
47
+ end
48
+
49
+ def inc_processes
50
+ @processes.each { |process| process[:value] += 1 }
51
+ end
52
+
32
53
  def kill
33
54
  Thread.kill(@th_tic) if @th_tic
34
55
  end
35
56
 
57
+ def timeout? type
58
+ @processes[type]
59
+ return unless @processes[type][:value] > @processes[type][:timeout]
60
+ @processes[type][:value] = 0
61
+ true
62
+ end
63
+
64
+ def process
65
+ timeout? :process
66
+ end
67
+
68
+ def playing_time
69
+ timeout? :playing_time
70
+ end
71
+
72
+ def ended
73
+ timeout? :ended
74
+ end
75
+
36
76
  def run
77
+ Thread.abort_on_exception = true
37
78
  @th_tic = Thread.new do
38
79
  loop do
39
- sleep 1
80
+ sleep 0.2
81
+ @processes[:process][:value] += 1
82
+ @processes[:playing_time][:value] += 1
83
+ @processes[:ended][:value] += 1
40
84
  @flag = true
41
85
  end
42
86
  end
@@ -49,8 +93,102 @@ class InOurTime
49
93
  end
50
94
  end
51
95
 
96
+ class PlayTime
97
+ def initialize(dur)
98
+ @duration = dur
99
+ @start_time = Time.now
100
+ update
101
+ end
102
+
103
+ def changed?
104
+ ! unchanged?
105
+ end
106
+
107
+ def read
108
+ store
109
+ format_time
110
+ end
111
+
112
+ def ended?
113
+ (@duration + 20) < @seconds
114
+ end
115
+
116
+ def unchanged?
117
+ (update == stored) || paused?
118
+ end
119
+
120
+ def store
121
+ @stored = @seconds
122
+ end
123
+
124
+ def stored
125
+ @stored
126
+ end
127
+
128
+ def plural x
129
+ x == 1 ? '' : 's'
130
+ end
131
+
132
+ def mins
133
+ @seconds / 60
134
+ end
135
+
136
+ def secs
137
+ @seconds % 60
138
+ end
139
+
140
+ def format x
141
+ x < 10 ? '0' + x.to_s : x.to_s
142
+ end
143
+
144
+ def format_minutes
145
+ format mins
146
+ end
147
+
148
+ def format_secs
149
+ format secs
150
+ end
151
+
152
+ def format_remaining_time
153
+ secs = @duration - @seconds
154
+ format(secs/60) + ':' + format(secs%60)
155
+ end
156
+
157
+ def format_time
158
+ ' (' + format_minutes + ':' + format_secs +
159
+ ' / ' + format_remaining_time + ')'
160
+ end
161
+
162
+ def update
163
+ @seconds = (Time.now - @start_time).to_i
164
+ end
165
+
166
+ def pause
167
+ @paused = Time.now
168
+ end
169
+
170
+ def paused?
171
+ @paused
172
+ end
173
+
174
+ def unpause
175
+ @start_time = @start_time + (Time.now - @paused)
176
+ @paused = false
177
+ end
178
+
179
+ def forward
180
+ @start_time -= 1.5
181
+ end
182
+
183
+ def rewind
184
+ @start_time += 1.5
185
+ end
186
+ end
187
+
52
188
  def initialize
53
- @content = ''
189
+ Thread.abort_on_exception = true
190
+ @queued = Array.new
191
+ @content = String.new
54
192
  @selected = 0
55
193
  clear
56
194
  print "\e[?25h"
@@ -80,7 +218,7 @@ class InOurTime
80
218
  STDIN.echo = true
81
219
  STDIN.cooked!
82
220
  puts "\n\n#{@error_msg}" if @error_msg
83
- puts 'Quitting...'
221
+ puts 'Quitting...'.freeze
84
222
  sleep 0.5
85
223
  exit code
86
224
  end
@@ -91,7 +229,7 @@ class InOurTime
91
229
  end
92
230
 
93
231
  def iot_print x, col = @text_colour, now = false
94
- content = ''
232
+ content = String.new
95
233
  content << x.colorize(col) if @config[:colour]
96
234
  content << x unless @config[:colour]
97
235
  unless now
@@ -101,9 +239,9 @@ class InOurTime
101
239
  end
102
240
  end
103
241
 
104
- def iot_puts x = '', col = @text_colour
105
- iot_print x, col
106
- iot_print "\n\r"
242
+ def iot_puts x = '', col = @text_colour, now = false
243
+ iot_print x, col, now
244
+ iot_print "\n\r", now
107
245
  end
108
246
 
109
247
  def clear_content
@@ -132,18 +270,18 @@ class InOurTime
132
270
  end
133
271
 
134
272
  def dev_mode?
135
- ENV['IN_OUR_TIME'] == 'development'
273
+ ENV['IN_OUR_TIME'] == 'development'.freeze
136
274
  end
137
275
 
138
276
  def puts_title colour
139
277
  title =
140
- %q{ _____ ____ _______ _
278
+ %q{ _____ ____ _______ _
141
279
  |_ _| / __ \ |__ __(_)
142
280
  | | _ __ | | | |_ _ _ __ | | _ _ __ ___ ___
143
281
  | | | '_ \ | | | | | | | '__| | | | | '_ ` _ \ / _ \
144
282
  _| |_| | | | | |__| | |_| | | | | | | | | | | | __/
145
283
  |_____|_| |_| \____/ \__,_|_| |_| |_|_| |_| |_|\___|
146
- }
284
+ }.freeze
147
285
 
148
286
  title.split("\n").map{|l| iot_print(l + "\r\n", colour)} if(window_width > 61)
149
287
  iot_puts("In Our Time\r", colour) unless(window_width > 61)
@@ -200,7 +338,7 @@ class InOurTime
200
338
 
201
339
  def set_height
202
340
  height = window_height
203
- while(height -2 % 10 != 0) ; height -=1 ; end
341
+ while(((height - 2) % 10) != 0) ; height -= 1 ; end
204
342
  height = 10 if height < 10
205
343
  @page_height = height if(@config[:page_height] == :auto)
206
344
  @page_height = @config[:page_height] unless(@config[:page_height] == :auto)
@@ -210,8 +348,8 @@ class InOurTime
210
348
  width = window_width
211
349
  while(width % 10 != 0) ; width -=1 ; end
212
350
  width = 20 if width < 20
213
- @page_width = width - 1 if(@config[:page_width] == :auto)
214
- @page_width = @config[:page_width] unless(@config[:page_width] == :auto)
351
+ @page_width = width - 1 if(@config[:page_width] == :auto)
352
+ @page_width = @config[:page_width] unless(@config[:page_width] == :auto)
215
353
  end
216
354
 
217
355
  def window_height
@@ -249,25 +387,16 @@ class InOurTime
249
387
  end
250
388
 
251
389
  def rss_addresses
390
+ filename = "/episodes/downloads.rss"
252
391
  host = 'http://www.bbc.co.uk/programmes'
253
- [ "/b006qykl/episodes/downloads.rss",
254
- "/p01drwny/episodes/downloads.rss",
255
- "/p01dh5yg/episodes/downloads.rss",
256
- "/p01f0vzr/episodes/downloads.rss",
257
- "/p01gvqlg/episodes/downloads.rss",
258
- "/p01gyd7j/episodes/downloads.rss"
259
- ].collect{|page| host + page}
392
+ [ "/b006qykl", "/p01drwny", "/p01dh5yg",
393
+ "/p01f0vzr", "/p01gvqlg", "/p01gyd7j"
394
+ ].collect{|page| host + page + filename}
260
395
  end
261
396
 
262
397
  def local_rss
263
- [
264
- "culture.rss",
265
- "history.rss",
266
- "in_our_time.rss",
267
- "philosophy.rss",
268
- "religion.rss",
269
- "science.rss"
270
- ]
398
+ [ "culture.rss", "history.rss", "in_our_time.rss",
399
+ "philosophy.rss", "religion.rss", "science.rss"]
271
400
  end
272
401
 
273
402
  def fetch_uri uri, file
@@ -342,13 +471,14 @@ class InOurTime
342
471
  end
343
472
 
344
473
  def build_program(bin)
345
- title = bin[tags[0]].shift.text
474
+ title = bin['title'].shift.text
346
475
  { title: title,
347
- subtitle: bin[tags[1]].shift.text,
348
- summary: bin[tags[2]].shift.text,
349
- duration: bin[tags[3]].shift.text,
350
- date: bin[tags[4]].shift.text[0..15],
351
- link: bin[tags[5]].shift.text,
476
+ subtitle: bin['itunes:subtitle'].shift.text,
477
+ summary: bin['itunes:summary'].shift.text,
478
+ duration: bin['itunes:duration'].shift.text,
479
+ date: bin['pubDate'].shift.text[0..15],
480
+ link: bin['link'].shift.text,
481
+ url: bin['url'].shift,
352
482
  have_locally: have_locally?(title)
353
483
  }
354
484
  end
@@ -376,6 +506,10 @@ class InOurTime
376
506
  bin[tag] = [] if bin[tag].nil?
377
507
  bin[tag] = @doc.xpath(item_path(tag))
378
508
  end
509
+ bin['url'] = []
510
+ @doc.xpath(item_path('enclosure')).each do |x|
511
+ bin['url'] << x.get('url')
512
+ end
379
513
  build_programs(bin)
380
514
  end
381
515
  uniquify_programs
@@ -418,12 +552,51 @@ class InOurTime
418
552
  redraw
419
553
  end
420
554
 
421
- def list_key
422
- title = @playing ? @playing : (@sorted_titles[@last_selected || 0])
555
+ def title_focus
556
+ @playing ? @playing : (@sorted_titles[@last_selected || 0])
557
+ end
558
+
559
+ def top_selected
560
+ @selected == 0
561
+ end
562
+
563
+ def end_selected
564
+ @selected == @titles_count - 1
565
+ end
566
+
567
+ def top_title_focus
568
+ title_focus == @sorted_titles.first
569
+ end
570
+
571
+ def end_title_focus
572
+ title_focus == @sorted_titles.last
573
+ end
574
+
575
+ def top_or_end?
576
+ top_selected || end_selected
577
+ end
578
+
579
+ def store_selected
580
+ @last_selected = @selected
581
+ end
582
+
583
+ def top_or_end_title_focus
584
+ top_title_focus || end_title_focus
585
+ end
586
+
587
+ def jump_key
423
588
  if top_or_end?
424
- draw_by_title title
589
+ if top_or_end_title_focus
590
+ if top_selected
591
+ list_end
592
+ else
593
+ list_top
594
+ end
595
+ else
596
+ draw_by_title title_focus
597
+ end
425
598
  else
426
- @last_selected = @selected
599
+ store_selected
427
600
  list_top_or_end
428
601
  end
429
602
  end
@@ -437,18 +610,12 @@ class InOurTime
437
610
  end
438
611
  end
439
612
 
440
- def top_or_end?
441
- @selected == 0 || @selected == @titles_count - 1
442
- end
443
-
444
613
  def list_top
445
- @last_selected = @selected
446
614
  @selected = 0
447
615
  draw_selected
448
616
  end
449
617
 
450
618
  def list_end
451
- @last_selected = @selected
452
619
  @selected = @titles_count - 1
453
620
  draw_selected
454
621
  end
@@ -497,7 +664,7 @@ class InOurTime
497
664
 
498
665
  def player_cmd
499
666
  if use_mpg123?
500
- "mpg123 --remote-err -Cqk#{pre_delay}"
667
+ "mpg123 -Cvk#{pre_delay}"
501
668
  else
502
669
  get_player
503
670
  end
@@ -517,12 +684,12 @@ class InOurTime
517
684
  @sorted_titles.each do |title|
518
685
  title.split(' ').each do |word|
519
686
  if distances[title].nil?
520
- distances[title] = Levenshtein::distance(search_term, word)
687
+ distances[title] = Levenshtein.distance(search_term, word)
521
688
  else
522
689
  distances[title] =
523
690
  distances[title] >
524
- Levenshtein::distance(search_term, word.downcase) ?
525
- Levenshtein::distance(search_term, word.downcase) :
691
+ Levenshtein.distance(search_term, word.downcase) ?
692
+ Levenshtein.distance(search_term, word.downcase) :
526
693
  distances[title]
527
694
  end
528
695
  end
@@ -534,11 +701,14 @@ class InOurTime
534
701
 
535
702
  def print_search_results results
536
703
  puts
537
- puts "0: Search Again!"
704
+ iot_print "0:", @count_sel_colour, :now
705
+ iot_puts " Search Again!", @system_colour, :now
706
+ puts
538
707
  puts
539
708
  5.times do |count|
540
- print "#{count + 1}: "
541
- puts results[count][0]
709
+ iot_print "#{count + 1}:", @count_sel_colour, :now
710
+ iot_print " #{results[count][0]}", @system_colour, :now
711
+ puts
542
712
  end
543
713
  puts
544
714
  end
@@ -555,7 +725,8 @@ class InOurTime
555
725
  end
556
726
 
557
727
  def get_search_term
558
- puts "Enter Search Term or just Return for Random:"
728
+ iot_puts "Enter Search Term or just Return for Random:", @system_colour, :now
729
+ puts
559
730
  puts
560
731
  print "Search Term: "
561
732
  gets.chomp
@@ -563,7 +734,7 @@ class InOurTime
563
734
 
564
735
  def get_search_choice
565
736
  print "Enter Choice: "
566
- temp = gets.chomp
737
+ temp = $stdin.getch.chomp
567
738
  temp == '0' ? :search_again : temp
568
739
  end
569
740
 
@@ -598,7 +769,7 @@ class InOurTime
598
769
  render
599
770
  10.times do
600
771
  begin
601
- res = Net::HTTP.get_response(URI.parse(prg[:link]))
772
+ res = Net::HTTP.get_response(URI.parse(prg[:url]))
602
773
  rescue SocketError => e
603
774
  print_error_and_delay "Error: Failed to connect to Internet! (#{e.class})"
604
775
  render
@@ -620,11 +791,10 @@ class InOurTime
620
791
  end
621
792
  retries += 1
622
793
  end
623
- if retries >= 10
624
- print_error_and_delay "Max retries downloading #{prg[:title]}"
625
- render
626
- @no_play = true
627
- end
794
+ return if retries < 10
795
+ print_error_and_delay "Max retries downloading #{prg[:title]}"
796
+ render
797
+ @no_play = true
628
798
  end
629
799
 
630
800
  # Cross-platform way of finding an executable in the $PATH.
@@ -647,16 +817,58 @@ class InOurTime
647
817
  quit 1
648
818
  end
649
819
 
820
+ def init_countdown(duration)
821
+ @play_time = PlayTime.new(duration) unless use_mpg123?
822
+ end
823
+
650
824
  def run_program prg
651
- download prg
652
825
  unless @no_play
653
826
  @playing = prg[:title]
654
827
  player = player_cmd.split(' ').first
655
- unknown_player(player) unless which(player)
828
+ unknown_player(player) unless which(File.basename player)
656
829
  window_title prg[:title]
657
830
  cmd = player_cmd + ' ' + filename_from_title(@playing)
658
831
  @messages = []
659
- @p_out, @p_in, @pid = PTY.spawn(cmd)
832
+ init_countdown prg[:duration].to_i
833
+ @player_th = Thread.new do
834
+ buf = ''
835
+ p_out, @p_in, @pid = PTY.spawn(cmd)
836
+ sleep 1
837
+ count = 0
838
+ loop do
839
+ unless use_mpg123?
840
+ sleep 1
841
+ else
842
+ x = p_out.getc unless p_out.eof?
843
+ if(((count >= 6) && (count <= 10)) ||
844
+ ((count > 15) && (count < 21)) )
845
+ buf << x
846
+ count += 1
847
+ elsif(((count == 0) && (x == 'T')) ||
848
+ ((count == 1) && (x == 'i')) ||
849
+ ((count == 2) && (x == 'm')) ||
850
+ ((count == 3) && (x == 'e')) ||
851
+ ((count == 4) && (x == ':')) ||
852
+ ((count == 5) && (x == ' ')) ||
853
+ ((count >= 12) && (count <= 15)))
854
+ count += 1
855
+ elsif count == 11
856
+ @running_time = buf
857
+ buf = ''
858
+ count += 1
859
+ elsif count == 21
860
+ @remaining_time = buf
861
+ buf = ''
862
+ count = 0
863
+ sleep 0.3
864
+ p_out.flush
865
+ else
866
+ count = 0
867
+ sleep 0.001
868
+ end
869
+ end
870
+ end
871
+ end
660
872
  end
661
873
  @no_play = nil
662
874
  end
@@ -677,6 +889,7 @@ class InOurTime
677
889
  begin
678
890
  @p_in.puts str
679
891
  rescue Errno::EIO
892
+ kill_audio
680
893
  reset
681
894
  end
682
895
  end
@@ -684,6 +897,8 @@ class InOurTime
684
897
  def pause
685
898
  return unless control_play?
686
899
  @paused = @paused ? false : true
900
+ @play_time.pause if @paused unless use_mpg123?
901
+ @play_time.unpause unless @paused unless use_mpg123?
687
902
  write_player " "
688
903
  redraw
689
904
  end
@@ -693,11 +908,15 @@ class InOurTime
693
908
  end
694
909
 
695
910
  def forward
696
- write_player ":" if control_play?
911
+ return unless control_play?
912
+ write_player ":"
913
+ @play_time.forward unless use_mpg123?
697
914
  end
698
915
 
699
916
  def rewind
700
- write_player ";" if control_play?
917
+ return unless control_play?
918
+ write_player ";"
919
+ @play_time.rewind unless use_mpg123?
701
920
  end
702
921
 
703
922
  def instructions
@@ -706,11 +925,30 @@ class InOurTime
706
925
  iot_print "for instructions", @system_colour
707
926
  end
708
927
 
928
+ def print_playing
929
+ iot_print("Playing: ", @count_colour)
930
+ end
931
+
932
+ def print_paused
933
+ iot_print("Paused: ", @count_colour)
934
+ end
935
+
936
+ def print_play_time
937
+ if use_mpg123?
938
+ iot_print(@playing, @selection_colour)
939
+ iot_print(' (' + @running_time, @selection_colour) unless @running_time.nil?
940
+ iot_print(' / ' + @remaining_time, @selection_colour) unless @remaining_time.nil?
941
+ iot_puts(')', @selection_colour) unless @running_time.nil?
942
+ else
943
+ iot_puts(@playing + @play_time.read, @selection_colour)
944
+ end
945
+ end
946
+
709
947
  def print_playing_maybe
710
948
  if @playing
711
- iot_print("Playing: ", @count_colour) unless @paused
712
- iot_print("Paused: ", @count_colour) if @paused
713
- iot_puts @playing, @selection_colour
949
+ print_playing unless @paused
950
+ print_paused if @paused
951
+ print_play_time
714
952
  elsif @started.nil?
715
953
  @started = true
716
954
  instructions
@@ -718,11 +956,19 @@ class InOurTime
718
956
  end
719
957
 
720
958
  def kill_audio
721
- return unless @playing
722
- @playing = nil
723
- return unless @pid.is_a?(Integer)
724
- Process.kill('QUIT', @pid)
725
- sleep 0.2
959
+ loop do
960
+ Thread.kill(@player_th) if @player_th
961
+ return unless @playing
962
+ begin
963
+ break unless @pid.is_a?(Integer)
964
+ Process.kill('QUIT', @pid)
965
+ _, status = Process.wait2 @pid
966
+ break if status.exited?
967
+ rescue Errno::ESRCH
968
+ break
969
+ end
970
+ sleep 0.2
971
+ end
726
972
  reset
727
973
  end
728
974
 
@@ -769,6 +1015,7 @@ class InOurTime
769
1015
 
770
1016
  def load_help_maybe
771
1017
  return unless help_option?
1018
+ @config[:colour] = false
772
1019
  help
773
1020
  puts
774
1021
  exit 0
@@ -776,37 +1023,43 @@ class InOurTime
776
1023
 
777
1024
  def help_screen
778
1025
  [] <<
779
- " In Our Time Player (#{@version})" <<
780
- " " <<
781
- " Play/Stop - X / Enter " <<
782
- " Next/Prev - Up / Down " <<
783
- " Next/Prev Page - Right / Left " <<
784
- " Sort - S " <<
785
- " Search - ? " <<
786
- " Theme Toggle - T " <<
787
- " List Top/End - L " <<
788
- " Update - U " <<
789
- " Download - D " <<
790
- " Info - I " <<
791
- " Help - H " <<
792
- " Quit - Q " <<
793
- " mpg123 Control - " <<
794
- " Pause/Resume - P / Spacebar " <<
795
- " Forward Skip - F " <<
796
- " Reverse Skip - R " <<
1026
+ " In Our Time Payer (#{@version}) " <<
797
1027
  " " <<
1028
+ " Play/Stop - Enter/X " <<
1029
+ " Next/Prev - Up/Down " <<
1030
+ " Next/Prev Page - Right/Left " <<
1031
+ " Arrange - A " <<
1032
+ " Search - ? " <<
1033
+ " Theme Toggle - T " <<
1034
+ " Jump Around List - J " <<
1035
+ " Update - U " <<
1036
+ " Download - D " <<
1037
+ " Enqueue - E " <<
1038
+ " Shuffle Play - S " <<
1039
+ " Shuffle Next - N " <<
1040
+ " Info - I " <<
1041
+ " Help - H " <<
1042
+ " Quit - Q " <<
1043
+ " mpg123 Control - " <<
1044
+ " Pause/Resume - P/Spacebar " <<
1045
+ " Forward Skip - F " <<
1046
+ " Reverse Skip - R " <<
798
1047
  "Config: #{CONFIG} "
799
1048
  end
800
1049
 
801
- def help_partial x,y; help_screen[x..y] end
802
- def help_title; help_partial(0, 1) end
803
- def help_main; help_partial(2, 13) end
804
- def help_cfg; help_partial(18, -1) end
1050
+ def title_xy; [0,0] end
1051
+ def main_xy; [1, help_screen.size - 7] end
1052
+ def mpg_xy; [help_screen.size - 6, -2] end
1053
+ def cfg_xy; [help_screen.size - 1, -1] end
1054
+ def help_partial(x); help_screen[x[0]..x[1]] end
1055
+ def help_title; help_partial(title_xy) end
1056
+ def help_main; help_partial(main_xy) end
1057
+ def help_cfg; help_partial(cfg_xy) end
805
1058
 
806
1059
  def help_mpg
807
- scr = help_partial(14,17)
808
- scr[0].rstrip! << ' (enabled) ' if use_mpg123?
809
- scr[0].rstrip! << ' (disabled) ' unless use_mpg123?
1060
+ scr = help_partial(mpg_xy)
1061
+ scr[0].rstrip! << ' (enabled) ' if use_mpg123?
1062
+ scr[0].rstrip! << ' (disabled) ' unless use_mpg123?
810
1063
  scr
811
1064
  end
812
1065
 
@@ -817,6 +1070,8 @@ class InOurTime
817
1070
  @count_colour if use_mpg123?
818
1071
  when :cfg
819
1072
  @system_colour
1073
+ when :title
1074
+ @system_colour
820
1075
  else
821
1076
  @text_colour
822
1077
  end
@@ -835,14 +1090,13 @@ class InOurTime
835
1090
  help_render :title
836
1091
  help_render :main
837
1092
  help_render :mpg
838
- help_render :cfg
1093
+ # help_render :cfg
839
1094
  end
840
1095
 
841
1096
  def help
842
1097
  unless @help
843
1098
  clear_content
844
1099
  print_help
845
- print_playing_maybe unless help_option?
846
1100
  @help = true
847
1101
  render
848
1102
  else
@@ -966,21 +1220,6 @@ class InOurTime
966
1220
  render
967
1221
  end
968
1222
 
969
- def check_process
970
- if(@playing && @pid.is_a?(Integer))
971
- begin
972
- write_player( "\e")
973
- if @pid.is_a? Integer
974
- Process.kill 0, @pid
975
- end
976
- rescue Errno::ESRCH
977
- reset
978
- end
979
- else
980
- @pid = nil
981
- end
982
- end
983
-
984
1223
  def page_forward
985
1224
  return unless @line_count < @titles_count
986
1225
  @selected = @line_count
@@ -1006,23 +1245,23 @@ class InOurTime
1006
1245
  end
1007
1246
 
1008
1247
  def play
1009
- if(@playing != @sorted_titles[@selected]) || (! @playing)
1010
- kill_audio
1011
- title = @sorted_titles[@selected]
1012
- pr = select_program title
1013
- run_program pr
1014
- redraw
1015
- else
1016
- kill_audio
1017
- end
1248
+ title = @sorted_titles[@selected]
1249
+ playing = @playing
1250
+ prg = select_program(title)
1251
+ download prg unless playing
1252
+ download prg if playing && (playing != title)
1253
+ kill_audio
1254
+ return unless (! playing) || (playing != title)
1255
+ run_program prg
1256
+ redraw
1018
1257
  end
1019
1258
 
1020
1259
  def update_key
1021
- update
1022
- parse_rss
1023
- sort_titles
1024
- @selected = 0
1025
- draw_selected
1260
+ update
1261
+ parse_rss
1262
+ sort_titles
1263
+ @selected = 0
1264
+ draw_selected
1026
1265
  end
1027
1266
 
1028
1267
  def download_key
@@ -1032,6 +1271,18 @@ class InOurTime
1032
1271
  draw_selected
1033
1272
  end
1034
1273
 
1274
+ def enqueue
1275
+ @queued << @sorted_titles[@selected]
1276
+ end
1277
+
1278
+ def next_program
1279
+ kill_audio
1280
+ end
1281
+
1282
+ def shuffle_key
1283
+ @queued = @sorted_titles.shuffle
1284
+ end
1285
+
1035
1286
  def quit_key
1036
1287
  kill_audio
1037
1288
  quit
@@ -1039,9 +1290,10 @@ class InOurTime
1039
1290
 
1040
1291
  def do_action ip
1041
1292
  case ip
1042
- when :pause, :forward, :rewind, :list_key, :page_forward, :page_back,
1293
+ when :pause, :forward, :rewind, :jump_key, :page_forward, :page_back,
1043
1294
  :previous, :next, :play, :sort_key, :theme_toggle, :update_key,
1044
- :info, :help, :quit_key, :search, :download_key
1295
+ :info, :help, :quit_key, :search, :download_key, :enqueue,
1296
+ :next_program, :shuffle_key
1045
1297
  self.send ip
1046
1298
  end
1047
1299
  end
@@ -1051,6 +1303,60 @@ class InOurTime
1051
1303
  @help = nil unless ip == :help
1052
1304
  end
1053
1305
 
1306
+ def ping_player
1307
+ write_player("\e")
1308
+ end
1309
+
1310
+ def check_player_process
1311
+ Process.kill 0, @pid
1312
+ end
1313
+
1314
+ def check_process
1315
+ return unless @playing
1316
+ if @pid.is_a?(Integer)
1317
+ begin
1318
+ write_player("\e")
1319
+ sleep 0.1
1320
+ if @pid.is_a? Integer
1321
+ check_player_process
1322
+ end
1323
+ rescue Errno::ESRCH
1324
+ kill_audio
1325
+ end
1326
+ else
1327
+ kill_audio
1328
+ unless @queued.empty?
1329
+ title = @queued.shift
1330
+ prg = select_program(title)
1331
+ download prg
1332
+ run_program(prg)
1333
+ draw_by_title title
1334
+ end
1335
+ end
1336
+ end
1337
+
1338
+ def check_finished
1339
+ return if use_mpg123?
1340
+ return unless @playing
1341
+ return unless @play_time.ended?
1342
+ kill_audio
1343
+ end
1344
+
1345
+ def check_tic
1346
+ return unless @tic.toc
1347
+ # check_process if @tic.process
1348
+ # check_finished if @tic.ended
1349
+ return unless @info.nil?
1350
+ return unless @help.nil?
1351
+ check_playing_time if @tic.playing_time
1352
+ end
1353
+
1354
+ def check_playing_time
1355
+ return unless @playing
1356
+ return unless @play_time.changed? unless use_mpg123?
1357
+ redraw
1358
+ end
1359
+
1054
1360
  def run
1055
1361
  ip = ''
1056
1362
  @tic = Tic.new
@@ -1061,7 +1367,7 @@ class InOurTime
1061
1367
  loop do
1062
1368
  ip = @key.read
1063
1369
  break unless ip == :no_event
1064
- check_process if @tic.toc
1370
+ check_tic
1065
1371
  do_events
1066
1372
  end
1067
1373
  reset_info_maybe ip
@@ -36,6 +36,7 @@ class KeyboardEvents
36
36
  end
37
37
 
38
38
  def run
39
+ Thread.abort_on_exception = true
39
40
  @key = Thread.new do
40
41
  while @event != :quit_key
41
42
  str = ''
@@ -72,6 +73,8 @@ class KeyboardEvents
72
73
  when "\e"
73
74
  @mode = :escape
74
75
  :no_event
76
+ when 'a', 'A'
77
+ :sort_key
75
78
  when 'd', 'D'
76
79
  :download_key
77
80
  when 'f', 'F'
@@ -80,8 +83,10 @@ class KeyboardEvents
80
83
  :help
81
84
  when 'i', 'I'
82
85
  :info
83
- when 'l', 'L'
84
- :list_key
86
+ when 'j', 'J'
87
+ :jump_key
88
+ when 'e', 'E'
89
+ :enqueue
85
90
  when 'p', 'P', ' '
86
91
  :pause
87
92
  when 'q', 'Q', "\u0003", "\u0004"
@@ -89,7 +94,9 @@ class KeyboardEvents
89
94
  when 'r', 'R'
90
95
  :rewind
91
96
  when 's', 'S'
92
- :sort_key
97
+ :shuffle_key
98
+ when 'n', 'N'
99
+ :next_program
93
100
  when 't', 'T'
94
101
  :theme_toggle
95
102
  when 'u', 'U'
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: in_our_time
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.3
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-12 00:00:00.000000000 Z
11
+ date: 2018-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oga
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '2.2'
19
+ version: 2.1.4
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '2.2'
26
+ version: 2.1.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: colorize
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -94,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
94
  version: '0'
95
95
  requirements: []
96
96
  rubyforge_project:
97
- rubygems_version: 2.5.1
97
+ rubygems_version: 2.6.13
98
98
  signing_key:
99
99
  specification_version: 4
100
100
  summary: Select, play, and download BBC 'In Our Time' podcasts - all from the command