sensible-cinema 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/FAQ +12 -0
  2. data/LICENSE +5 -0
  3. data/README +7 -0
  4. data/Rakefile +30 -0
  5. data/TODO +106 -0
  6. data/VERSION +1 -0
  7. data/bin/bad_digit10.bmp +0 -0
  8. data/bin/bad_digit11.bmp +0 -0
  9. data/bin/bad_digit12.bmp +0 -0
  10. data/bin/bad_digit13.bmp +0 -0
  11. data/bin/bad_digit14.bmp +0 -0
  12. data/bin/bad_digit15.bmp +0 -0
  13. data/bin/bad_digit16.bmp +0 -0
  14. data/bin/bad_digit17.bmp +0 -0
  15. data/bin/bad_digit18.bmp +0 -0
  16. data/bin/bad_digit19.bmp +0 -0
  17. data/bin/bad_digit2.bmp +0 -0
  18. data/bin/bad_digit20.bmp +0 -0
  19. data/bin/bad_digit21.bmp +0 -0
  20. data/bin/bad_digit22.bmp +0 -0
  21. data/bin/bad_digit3.bmp +0 -0
  22. data/bin/bad_digit4.bmp +0 -0
  23. data/bin/bad_digit5.bmp +0 -0
  24. data/bin/bad_digit6.bmp +0 -0
  25. data/bin/bad_digit7.bmp +0 -0
  26. data/bin/bad_digit8.bmp +0 -0
  27. data/bin/bad_digit9.bmp +0 -0
  28. data/bin/hours.bmp +0 -0
  29. data/bin/minute_ones.bmp +0 -0
  30. data/bin/minute_tens.bmp +0 -0
  31. data/bin/scene-skipper +58 -0
  32. data/bin/second_ones.bmp +0 -0
  33. data/bin/second_tens.bmp +0 -0
  34. data/ext/mkrf_conf.rb +5 -0
  35. data/lib/blanker.rb +54 -0
  36. data/lib/keyboard_input.rb +45 -0
  37. data/lib/mouse.rb +60 -0
  38. data/lib/muter.rb +48 -0
  39. data/lib/ocr.rb +57 -0
  40. data/lib/overlayer.rb +341 -0
  41. data/lib/screen_tracker.rb +160 -0
  42. data/spec/common.rb +43 -0
  43. data/spec/convert_image.rb +8 -0
  44. data/spec/images/4.bmp +0 -0
  45. data/spec/images/black.bmp +0 -0
  46. data/spec/images/colon.bmp +0 -0
  47. data/spec/images/hulu_0.bmp +0 -0
  48. data/spec/images/hulu_2.bmp +0 -0
  49. data/spec/images/hulu_2_4.bmp +0 -0
  50. data/spec/images/hulu_3.bmp +0 -0
  51. data/spec/images/hulu_3_4.bmp +0 -0
  52. data/spec/images/hulu_4.bmp +0 -0
  53. data/spec/images/hulu_4_4.bmp +0 -0
  54. data/spec/images/hulu_5.bmp +0 -0
  55. data/spec/images/hulu_7.bmp +0 -0
  56. data/spec/images/hulu_slash.bmp +0 -0
  57. data/spec/images/vlc_0.bmp +0 -0
  58. data/spec/images/vlc_2_6.bmp +0 -0
  59. data/spec/images/vlc_4.bmp +0 -0
  60. data/spec/images/vlc_5.bmp +0 -0
  61. data/spec/images/vlc_6.bmp +0 -0
  62. data/spec/images/vlc_9.bmp +0 -0
  63. data/spec/images/vlc_colon.bmp +0 -0
  64. data/spec/mouse_forever.rb +2 -0
  65. data/spec/open.bat +1 -0
  66. data/spec/silence.wav +0 -0
  67. data/spec/spec.blanker.rb +35 -0
  68. data/spec/spec.keyboard_input.rb +56 -0
  69. data/spec/spec.mouse.rb +11 -0
  70. data/spec/spec.muter.rb +33 -0
  71. data/spec/spec.ocr.rb +33 -0
  72. data/spec/spec.overlayer.rb +331 -0
  73. data/spec/spec.screen_tracker.rb +211 -0
  74. data/spec/test_yaml.yml +4 -0
  75. data/vendor/gocr048.exe +0 -0
  76. data/zamples/players/captures/hulu full screen non hour.jpg +0 -0
  77. data/zamples/players/captures/hulu full screen over hour.jpg +0 -0
  78. data/zamples/players/captures/silence.bmp +0 -0
  79. data/zamples/players/captures/vlc grab over one hour file over one hour play.bmp +0 -0
  80. data/zamples/players/captures/vlc2.bmp +0 -0
  81. data/zamples/players/captures/vlc_full_screen_slider under one hour.bmp +0 -0
  82. data/zamples/players/captures/youtube full screen big screen.jpg +0 -0
  83. data/zamples/players/how_to +21 -0
  84. data/zamples/players/hulu_full_screened_over_an_hour.yml +23 -0
  85. data/zamples/players/vlc_full_screened.yml +6 -0
  86. data/zamples/players/vlc_full_screened_over_hour.yml +23 -0
  87. data/zamples/players/vlc_non_full_screened.yml +19 -0
  88. data/zamples/players/vlc_non_full_screened_under_an_hour.yml +19 -0
  89. data/zamples/scene_lists/disney_cars.yml +13 -0
  90. data/zamples/scene_lists/happy_feet.yml +7 -0
  91. data/zamples/scene_lists/mute_list.yml +15 -0
  92. metadata +286 -0
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/common')
2
+ require_relative '../lib/keyboard_input'
3
+
4
+ describe KeyboardInput do
5
+
6
+ class Go
7
+ @time = 58
8
+ def self.cur_time
9
+ @time += 1
10
+ end
11
+
12
+ def self.got
13
+ @got
14
+ end
15
+
16
+ @muted = true
17
+ class << self
18
+ attr_accessor :muted
19
+ end
20
+
21
+ def self.status
22
+ @muted = !@muted
23
+ if @muted
24
+ "muted"
25
+ else
26
+ "unmuted"
27
+ end
28
+ end
29
+
30
+ def self.keyboard_input input
31
+ @got = input
32
+ end
33
+ end
34
+
35
+ before do
36
+ @a = KeyboardInput.new Go
37
+ Go.muted = true
38
+ end
39
+
40
+ it "should display on one line" do
41
+ @a.get_line_printout.should include("\b\b\b")
42
+ end
43
+
44
+ it "should display whether muted or not" do
45
+ @a.get_line_printout.should include("unmuted")
46
+ @a.get_line_printout.should_not include("unmuted")
47
+ end
48
+
49
+ it "should translate keys to characters" do
50
+ @a.handle_keystroke 77
51
+ Go.got.should == "M"
52
+ @a.handle_keystroke 109
53
+ Go.got.should == "m"
54
+ end
55
+
56
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'sane'
3
+ require_relative '../lib/mouse'
4
+
5
+ begin
6
+ Timeout::timeout(2) {
7
+ Mouse::jitter_forever_in_own_thread.join
8
+ }
9
+ rescue
10
+ end
11
+ puts 'mouse should have moved...'
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + "/common"
2
+ require_relative '../lib/muter'
3
+
4
+ describe 'manual muter' do
5
+ # functional test
6
+
7
+ 3.times {
8
+ Muter.mute!
9
+ puts 'muted'
10
+ sleep 1
11
+ Muter.unmute!
12
+ puts 'unmuted'
13
+ sleep 1
14
+ }
15
+ # these rest *should* be able to pass...
16
+
17
+ Muter.mute!
18
+ Muter.mute!
19
+ puts 'silence'
20
+ sleep 1
21
+ Muter.unmute!
22
+ puts 'non silence'
23
+ sleep 1
24
+ Muter.unmute!
25
+ puts 'non silence'
26
+ sleep 1
27
+ puts 'single takes'
28
+ p Benchmark.realtime { 1.times{Muter.hit_volume_down_key}}
29
+ puts 'triple takes'
30
+ p Benchmark.realtime { 1.times{Muter.unmute!}} # 0.00023848s
31
+ # seems actually like reasonable speed
32
+ Muter.unmute!
33
+ end
data/spec/spec.ocr.rb ADDED
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/common'
2
+ require_relative "../lib/ocr"
3
+
4
+ describe OCR do
5
+
6
+ it "should be able to output help output" do
7
+ OCR.version.should_not be_blank
8
+ end
9
+
10
+ it "should be able to grab some digits" do
11
+ success = true
12
+ for file in Dir['images/*[0-9].bmp']
13
+ options = {}
14
+ options[:should_invert] = true if file =~ /hulu/
15
+ file =~ /(.)\.bmp/
16
+ expected_digit = $1.to_i
17
+ if OCR.identify_digit(File.binread(file), options) != expected_digit
18
+ p "fail:" + file
19
+ success = false
20
+ end
21
+ end
22
+ fail unless success
23
+ end
24
+
25
+ it "should be able to grab a colon" do
26
+ OCR.identify_digit(File.binread("images/colon.bmp"), :might_be_colon => true).should == ":"
27
+ end
28
+
29
+ it "should return nil if it can't identify a digit" do
30
+ OCR.identify_digit(File.binread("images/black.bmp")).should be_nil
31
+ end
32
+
33
+ end
@@ -0,0 +1,331 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/common')
2
+ require_relative '../lib/overlayer'
3
+
4
+ # tell it not to actually mute during testing...
5
+ $DEBUG = true
6
+
7
+ def start_good_blank
8
+ assert !@o.blank?
9
+ end
10
+
11
+ def start_bad_blank
12
+ assert @o.blank?
13
+ end
14
+
15
+
16
+ describe OverLayer do
17
+
18
+ before do
19
+ File.write 'temp.yml', YAML.dump({:mutes => {2.0 => 4.0}} )
20
+ @o = OverLayer.new('temp.yml')
21
+ end
22
+
23
+ after do
24
+ Thread.join_all_others
25
+ File.delete 'temp.yml'
26
+ end
27
+
28
+ def start_good
29
+ assert !@o.muted?
30
+ sleep 1
31
+ end
32
+
33
+ def start_bad
34
+ assert @o.muted? # note this uses @o!
35
+ sleep 1
36
+ end
37
+
38
+ it 'should reject overlapping settings...I guess'
39
+
40
+ it 'should be able to mute' do
41
+ # several combinations...
42
+ assert !@o.muted?
43
+ @o.mute!
44
+ assert @o.muted?
45
+ @o.unmute!
46
+ assert !@o.muted?
47
+ @o.mute!
48
+ assert @o.muted?
49
+ end
50
+
51
+ context 'given you know when to start' do
52
+
53
+ it 'should mute based on time' do
54
+ @o.start_thread
55
+ # make sure we enter the mute section
56
+ sleep 2.25
57
+ start_bad
58
+ sleep 1
59
+ start_good
60
+ end
61
+
62
+ it 'should handle multiple mutes in a row' do
63
+ File.write 'temp.yml', YAML.dump({:mutes => {2.0 => 4.0, 5.0 => 7.0}})
64
+ @o = OverLayer.new 'temp.yml'
65
+ @o.start_thread
66
+ sleep 2.5
67
+ start_bad # 1s
68
+ sleep 2 # => 5.5
69
+ start_bad
70
+ end
71
+
72
+ it 'should be able to mute teeny sequences' do
73
+ File.write 'temp.yml', YAML.dump({:mutes => {0.0001 => 0.0002, 1.0 => 1.0001}})
74
+ o = OverLayer.new 'temp.yml'
75
+ o.continue_until_past_all false
76
+ end
77
+ end
78
+
79
+ context 'startup' do
80
+ it 'should allow you to change the current time' do
81
+ @o.start_thread
82
+ sleep 0.1 # wow ruby is slow...
83
+ assert @o.cur_time > 0
84
+ @o.set_seconds 5
85
+ sleep 0.1
86
+ assert @o.cur_time > 5
87
+ end
88
+
89
+ it 'should be able to hit keys to affect input' do
90
+ @o = OverLayer.new 'test_yaml.yml'
91
+ @o.cur_time
92
+ @o.keyboard_input 'm'
93
+ assert @o.cur_time > 59
94
+ @o.keyboard_input 'M'
95
+ assert @o.cur_time < 59
96
+ 60.times {
97
+ @o.keyboard_input 's'
98
+ }
99
+ assert @o.cur_time > 59
100
+ 60.times {
101
+ @o.keyboard_input 'S'
102
+ }
103
+ assert @o.cur_time < 59
104
+ 600.times {
105
+ @o.keyboard_input 't'
106
+ }
107
+ assert @o.cur_time > 59
108
+ 600.times {
109
+ @o.keyboard_input 'T'
110
+ }
111
+ assert @o.cur_time < 59
112
+
113
+ end
114
+
115
+ end
116
+
117
+ it 'should have help output' do
118
+ @o.status.should include("MmSs")
119
+ end
120
+
121
+ it 'should allow for real yaml files somehow and use it' do
122
+ # 2 - 3 , 4-5 should be muted
123
+ @o = OverLayer.new 'test_yaml.yml'
124
+ @o.start_thread
125
+ start_good # takes 1s
126
+ sleep 1.25
127
+ start_bad
128
+ start_good
129
+ start_bad
130
+ start_good
131
+ end
132
+
133
+ def write_yaml yaml
134
+ File.write 'temp.yml', yaml
135
+ end
136
+
137
+ it 'should allow for 1:00.0 minute style input' do
138
+ write_yaml <<YAML
139
+ :mutes:
140
+ "0:02.0" : "0:03.0"
141
+ YAML
142
+ @o = OverLayer.new 'temp.yml'
143
+ @o.start_thread
144
+ start_good
145
+ start_good
146
+ sleep 0.25
147
+ start_bad
148
+ start_good
149
+ end
150
+
151
+ it "should reload the YAML file on the fly to allow for editing it" do
152
+ # start it with one far later
153
+ write_yaml <<YAML
154
+ :mutes:
155
+ "0:11.0" : "0:12.0"
156
+ YAML
157
+ @o = OverLayer.new 'temp.yml'
158
+ @o.start_thread
159
+ start_good
160
+ write_yaml <<YAML
161
+ :mutes:
162
+ "0:00.0" : "0:01.5"
163
+ YAML
164
+ # go forward a tenth
165
+ # should reload it...
166
+ @o.keyboard_input 'T'
167
+ sleep 0.1 # blug
168
+ start_bad
169
+ start_good
170
+ end
171
+
172
+ it "should translate yaml well" do
173
+ yaml = <<-YAML
174
+ :mutes:
175
+ "0:02.0" : "0:03.0"
176
+ :blank_outs:
177
+ "0:02.0" : "0:03.0"
178
+ YAML
179
+ out = OverLayer.translate_yaml yaml
180
+ out[:mutes].to_a.first.should == [2.0, 3.0]
181
+ out[:blank_outs].to_a.first.should == [2.0, 3.0]
182
+ yaml = <<-YAML
183
+ :mutes:
184
+ "1:02.11" : "1:03.0"
185
+ YAML
186
+ out = OverLayer.translate_yaml yaml
187
+ out[:mutes].to_a.first.should == [62.11, 63.0]
188
+ end
189
+
190
+ it "should translate strings as well as symbols" do
191
+ yaml = <<-YAML
192
+ mutes:
193
+ "1" : "3
194
+ YAML
195
+ out = OverLayer.translate_yaml yaml
196
+ out[:mutes].to_a.first.should == [1, 3]
197
+ end
198
+
199
+ it "should disallow negative length intervals"
200
+
201
+ it "should allow for 1:01:00.0 (double colon) style input" do
202
+ write_yaml <<-YAML
203
+ :mutes:
204
+ "1:00.11" : "1:03.0"
205
+ YAML
206
+ @o = OverLayer.new 'temp.yml'
207
+ @o.start_thread
208
+ start_good
209
+ @o.set_seconds 61
210
+ sleep 0.1 # ruby rox again!
211
+ start_bad
212
+ sleep 2
213
+ start_good
214
+ end
215
+
216
+ it "should be able to tell the player to sync to the closest second when the screen only changes" do
217
+ @o.start_thread
218
+ start = Time.now
219
+ while((Time.now - start) < 3) do
220
+ @o.timestamp_changed nil, nil
221
+ sleep 0.1
222
+ end
223
+ @o.cur_time.should be < 1
224
+ sleep 1
225
+ 10.times { @o.timestamp_changed(nil, nil) }
226
+ @o.cur_time.should be >= 1
227
+ sleep 0.6
228
+ @o.timestamp_changed nil, nil
229
+ @o.cur_time.should be >= 2
230
+ end
231
+
232
+ it "should be able to handle it when the sync message includes a new timestamp" do
233
+ @o.start_thread
234
+ @o.timestamp_changed "1:00:01", 0
235
+ @o.cur_time.should be > 60*60
236
+ @o.timestamp_changed "0:00:01", 0
237
+ @o.cur_time.should be < 60*60
238
+ end
239
+
240
+ it "should handle deltas to created timestamps" do
241
+ @o.start_thread
242
+ @o.timestamp_changed "1:00:00", 1
243
+ @o.cur_time.should be >= 60*60 + 1
244
+ end
245
+
246
+ context "should handle blanks, too" do
247
+
248
+ it "should be able to discover next states well" do
249
+ for type in [:blank_outs, :mutes] do
250
+ @o = OverLayer.new_raw({type => {2.0 => 4.0}})
251
+ @o.discover_state(type, 3).should == [2.0, 4.0, true]
252
+ @o.discover_state(type, 0.5).should == [2.0, 4.0, false]
253
+ @o.discover_state(type, 5).should == [nil, nil, :done]
254
+ @o.discover_state(type, 2.0).should == [2.0, 4.0, true]
255
+ @o.discover_state(type, 4.0).should == [nil, nil, :done]
256
+ end
257
+ end
258
+
259
+ context "with a list of blanks" do
260
+
261
+ it "should blank" do
262
+ @o = OverLayer.new_raw({:blank_outs => {2.0 => 4.0}})
263
+
264
+ @o.start_thread
265
+ start_good_blank
266
+ sleep 1
267
+ start_good_blank
268
+ sleep 1.1
269
+ start_bad_blank
270
+ sleep 2
271
+ start_good_blank
272
+ end
273
+ end
274
+
275
+ def at time
276
+ @o.stub!(:cur_time) {
277
+ time
278
+ }
279
+ yield
280
+ end
281
+
282
+ context "mixed blanks and others" do
283
+ it "should allow for mixed" do
284
+ @o = OverLayer.new_raw({:mutes => {2.0 => 3.5}, :blank_outs => {3.0 => 4.0}})
285
+ at(1.5) do
286
+ @o.cur_time.should == 1.5
287
+ @o.get_current_state.should == [false, false, 2.0]
288
+ end
289
+
290
+ at(2.0) do
291
+ @o.get_current_state.should == [true, false, 3.0]
292
+ end
293
+
294
+ at(3.0) do
295
+ @o.get_current_state.should == [true, true, 3.5]
296
+ end
297
+
298
+ at(3.75) do
299
+ @o.get_current_state.should == [false, true, 4.0]
300
+ end
301
+
302
+ at(4) do
303
+ @o.get_current_state.should == [false, false, :done]
304
+ end
305
+
306
+ end
307
+ end
308
+
309
+ it "should not fail with verbose on, after it's past next states" do
310
+ at(500_000) do
311
+ @o.status.should == "Current time: 138:53:20.0 no more actions after this point... (HhMmSsTtdvq): "
312
+ end
313
+
314
+ end
315
+
316
+ end
317
+
318
+ it "should be human readable" do
319
+ @o.translate_time_to_human_readable(3600).should == "1:00:00.0"
320
+ @o.translate_time_to_human_readable(3600.0).should == "1:00:00.0"
321
+ @o.translate_time_to_human_readable(3601).should == "1:00:01.0"
322
+ @o.translate_time_to_human_readable(3661).should == "1:01:01.0"
323
+ end
324
+
325
+ it "should accept human readable input" do
326
+ o = OverLayer.new 'temp.yml', "01:01.5"
327
+ o.cur_time.should be == 61.5
328
+
329
+ end
330
+
331
+ end
@@ -0,0 +1,211 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/common')
2
+ require_relative '../lib/overlayer'
3
+ require_relative '../lib/screen_tracker'
4
+ require 'pathname'
5
+
6
+ describe ScreenTracker do
7
+
8
+ if RUBY_PLATFORM =~ /java/
9
+ it "is pending a java bug..."
10
+ else
11
+ before(:all) do
12
+ begin
13
+ Win32::Screenshot.window(/silence.wav/, 0) {}
14
+ rescue
15
+ # this way we'll only have one up...
16
+ @pid1 = IO.popen('open.bat').pid # jruby can't open it directly yet
17
+ sleep 2
18
+ end
19
+ end
20
+
21
+ before do
22
+ @a = ScreenTracker.new(/silence.*VLC/,10,10,20,20)
23
+ end
24
+
25
+ it "can take a regex or string" do
26
+ ScreenTracker.new(/silence.*VLC/,10,10,20,20)
27
+ ScreenTracker.new("silence",10,10,20,20)
28
+ end
29
+
30
+ it "should be able to grab a picture from screen coords...probably from the current active window" do
31
+ @a.get_bmp.should_not be_nil
32
+ end
33
+
34
+ it "should loop if unable to find the right window" do
35
+ proc {
36
+ Timeout::timeout(1) do
37
+ ScreenTracker.new("unknown window",10,10,20,20)
38
+ end
39
+ }.should raise_error(Timeout::Error)
40
+ end
41
+
42
+ it "should be at least somewhat fast" do
43
+ Benchmark.realtime { @a.get_bmp }.should be < 0.3
44
+ end
45
+
46
+ it "should not allow for negative widths" do
47
+ proc {ScreenTracker.new("VLC",10,10,-20,20)}.should raise_error
48
+ end
49
+
50
+ it "should disallow size 0 widths" do
51
+ proc {ScreenTracker.new("VLC",10,10,0,0)}.should raise_error
52
+ end
53
+
54
+ it "should have different bmp if sizes different" do
55
+ a = ScreenTracker.new("VLC",10,10,5,5)
56
+ assert a.get_relative_coords == [10,10,15,15]
57
+ b = ScreenTracker.new("VLC",10,10,50,50)
58
+ assert a.get_bmp != b.get_bmp
59
+ end
60
+
61
+ it "should allow for straight desktop if they specify Desktop or desktop" do
62
+ a = ScreenTracker.new("desktop",0,0,100,100)
63
+ end
64
+
65
+ context "negative numbers should result in an offset" do
66
+
67
+ it "should allow for negative sizes" do
68
+ a = ScreenTracker.new("VLC",-10,10,5,5)
69
+ a.get_bmp
70
+ a = ScreenTracker.new("VLC",-10,-10,10,10) # right to the edge
71
+ a.get_bmp
72
+ a = ScreenTracker.new("VLC",10,-10,5,5)
73
+ a.get_bmp
74
+ end
75
+
76
+ it "should assign right coords" do
77
+ a = ScreenTracker.new("VLC",-10,-10,5,5)
78
+ a.get_bmp
79
+ x,y,x2,y2=a.get_relative_coords
80
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd("VLC")
81
+ always_zero, always_zero, max_x, max_y = Win32::Screenshot::BitmapMaker.dimensions_for(hwnd)
82
+ x.should == max_x-10
83
+ y.should == max_y-10
84
+ x2.should == x+5
85
+ y2.should == y+5
86
+ end
87
+
88
+ it "should look different with negative than with positive" do
89
+ a = ScreenTracker.new("VLC",10,10,50,50)
90
+ b = ScreenTracker.new("VLC",10,10,50,50)
91
+ c = ScreenTracker.new("VLC",-99,-99,50,50)
92
+ assert a.get_bmp == b.get_bmp
93
+ assert c.get_relative_coords != b.get_relative_coords
94
+ cb = c.get_bmp
95
+ bb = b.get_bmp
96
+ c.get_bmp.length == b.get_bmp.length
97
+ assert c.get_bmp != b.get_bmp
98
+ end
99
+
100
+ it "should fail with out of bounds or zero sizes" do
101
+ proc { a = ScreenTracker.new(/silence.*VLC/,-10,10,20,20) }.should raise_error
102
+ proc { a = ScreenTracker.new(/silence.*VLC/,10,-10,20,20) }.should raise_error
103
+ proc { a = ScreenTracker.new(/silence.*VLC/,-10,10,0,2) }.should raise_error
104
+ proc { a = ScreenTracker.new(/silence.*VLC/,10,10,2,0) }.should raise_error
105
+ end
106
+
107
+ end
108
+
109
+ # lodo: this 7 looks rather redundant...
110
+ it "should parse yaml appropro" do
111
+ yaml = <<-YAML
112
+ name: VLC
113
+ x: 32
114
+ y: 34
115
+ width: 100
116
+ height: 20
117
+ digits:
118
+ :hours:
119
+ :minute_tens:
120
+ - -90
121
+ - 7
122
+ :minute_ones:
123
+ - -82
124
+ - 7
125
+ :second_tens:
126
+ - -72
127
+ - 7
128
+ :second_ones:
129
+ - -66
130
+ - 7
131
+ YAML
132
+ a = ScreenTracker.new_from_yaml(yaml,nil)
133
+ a.get_relative_coords.should == [32,34,132,54]
134
+ end
135
+
136
+ it "should be able to dump its contents" do
137
+ @a.dump_bmp
138
+ assert File.exist?('dump.bmp') && File.exist?('all.dump.bmp')
139
+ end
140
+
141
+ context "given a real player that is moving" do
142
+
143
+ before do
144
+ @a = ScreenTracker.new("silence.wav", -111, -16, 86, 13)
145
+ end
146
+
147
+ it "should be able to poll the screen to know when something changes" do
148
+ @a.wait_till_next_change
149
+ # it updates every 1 second...
150
+ Benchmark.realtime { @a.wait_till_next_change }.should be > 0.2
151
+ @a.dump_bmp # for debugging...
152
+ end
153
+
154
+ context "using OCR" do
155
+
156
+ before do
157
+ # vlc_non_full_screened_under_an_hour.yml
158
+ @a = ScreenTracker.new("silence.wav", -111, -16, 86, 13,
159
+ {:hours => nil, :minute_tens => [-90,7], :minute_ones => [-82, 7], :second_tens => [-72, 7], :second_ones => [-66, 7]} )
160
+ end
161
+
162
+ it "should be able to snapshot digits" do
163
+ @a.dump_bmp
164
+ Pathname.new('minute_tens.bmp').should exist
165
+ Pathname.new('minute_tens.bmp').size.should be > 0
166
+ Pathname.new('hours.bmp').should_not exist
167
+ end
168
+
169
+ it "should use OCR against the changes appropriately" do
170
+ output = @a.wait_till_next_change
171
+ output[0].should be_a(String)
172
+ output[0].should include("00:0")# let's hope it runs quickly...
173
+ output[0].should match(/[1-9]/)
174
+ end
175
+
176
+ context "with an OCR that can change willy-nilly from hour to second" do
177
+ it "should ocr slash...[in other]"
178
+ it "with VLC should be able to recognize when it goes past an hour somehow...probably by presence of hourly colon" # might already do this
179
+ it "should work with hulu too, because of ads"
180
+ end
181
+
182
+ it "should be able to use invert on images" do
183
+ @a = ScreenTracker.new("silence.wav", -111, -16, 86, 13,
184
+ {:should_invert => true, :hours => nil, :minute_tens => [-90,7], :minute_ones => [-82, 7], :second_tens => [-72, 7], :second_ones => [-66, 7]} )
185
+ got_it = nil
186
+ OCR.stub!(:identify_digit) {|*args|
187
+ got_it = args
188
+ }
189
+ @a.identify_digit('some binary bitmap data')
190
+ got_it[1][:should_invert].should be_true
191
+ end
192
+
193
+ end
194
+
195
+ after(:all) do
196
+ begin
197
+ # bring redcar to the foreground
198
+ # this seg faults on windows 7 for me for some reason when run inside the editor itself...swt bug?
199
+ unless Socket.gethostname == "PACKRD-1GK7V"
200
+ Win32::Screenshot.window(/universal/, 0) rescue nil
201
+ end
202
+ Process.kill 9, @pid1 rescue nil # need this re-started each time or the screen won't change for the screen changing test
203
+ FileUtils.rm_rf Dir['*.bmp'] unless $DEBUG
204
+ rescue => e
205
+ puts 'got after bug:', e # until this bug is fixed... http://github.com/rspec/rspec-core/issues#issue/21
206
+ throw e
207
+ end
208
+ end
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,4 @@
1
+ title: Forever Strong
2
+ :mutes:
3
+ 2.0 : 3.0
4
+ 4.0 : 5.0
Binary file
Binary file