sensible-cinema 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/FAQ +12 -0
- data/LICENSE +5 -0
- data/README +7 -0
- data/Rakefile +30 -0
- data/TODO +106 -0
- data/VERSION +1 -0
- data/bin/bad_digit10.bmp +0 -0
- data/bin/bad_digit11.bmp +0 -0
- data/bin/bad_digit12.bmp +0 -0
- data/bin/bad_digit13.bmp +0 -0
- data/bin/bad_digit14.bmp +0 -0
- data/bin/bad_digit15.bmp +0 -0
- data/bin/bad_digit16.bmp +0 -0
- data/bin/bad_digit17.bmp +0 -0
- data/bin/bad_digit18.bmp +0 -0
- data/bin/bad_digit19.bmp +0 -0
- data/bin/bad_digit2.bmp +0 -0
- data/bin/bad_digit20.bmp +0 -0
- data/bin/bad_digit21.bmp +0 -0
- data/bin/bad_digit22.bmp +0 -0
- data/bin/bad_digit3.bmp +0 -0
- data/bin/bad_digit4.bmp +0 -0
- data/bin/bad_digit5.bmp +0 -0
- data/bin/bad_digit6.bmp +0 -0
- data/bin/bad_digit7.bmp +0 -0
- data/bin/bad_digit8.bmp +0 -0
- data/bin/bad_digit9.bmp +0 -0
- data/bin/hours.bmp +0 -0
- data/bin/minute_ones.bmp +0 -0
- data/bin/minute_tens.bmp +0 -0
- data/bin/scene-skipper +58 -0
- data/bin/second_ones.bmp +0 -0
- data/bin/second_tens.bmp +0 -0
- data/ext/mkrf_conf.rb +5 -0
- data/lib/blanker.rb +54 -0
- data/lib/keyboard_input.rb +45 -0
- data/lib/mouse.rb +60 -0
- data/lib/muter.rb +48 -0
- data/lib/ocr.rb +57 -0
- data/lib/overlayer.rb +341 -0
- data/lib/screen_tracker.rb +160 -0
- data/spec/common.rb +43 -0
- data/spec/convert_image.rb +8 -0
- data/spec/images/4.bmp +0 -0
- data/spec/images/black.bmp +0 -0
- data/spec/images/colon.bmp +0 -0
- data/spec/images/hulu_0.bmp +0 -0
- data/spec/images/hulu_2.bmp +0 -0
- data/spec/images/hulu_2_4.bmp +0 -0
- data/spec/images/hulu_3.bmp +0 -0
- data/spec/images/hulu_3_4.bmp +0 -0
- data/spec/images/hulu_4.bmp +0 -0
- data/spec/images/hulu_4_4.bmp +0 -0
- data/spec/images/hulu_5.bmp +0 -0
- data/spec/images/hulu_7.bmp +0 -0
- data/spec/images/hulu_slash.bmp +0 -0
- data/spec/images/vlc_0.bmp +0 -0
- data/spec/images/vlc_2_6.bmp +0 -0
- data/spec/images/vlc_4.bmp +0 -0
- data/spec/images/vlc_5.bmp +0 -0
- data/spec/images/vlc_6.bmp +0 -0
- data/spec/images/vlc_9.bmp +0 -0
- data/spec/images/vlc_colon.bmp +0 -0
- data/spec/mouse_forever.rb +2 -0
- data/spec/open.bat +1 -0
- data/spec/silence.wav +0 -0
- data/spec/spec.blanker.rb +35 -0
- data/spec/spec.keyboard_input.rb +56 -0
- data/spec/spec.mouse.rb +11 -0
- data/spec/spec.muter.rb +33 -0
- data/spec/spec.ocr.rb +33 -0
- data/spec/spec.overlayer.rb +331 -0
- data/spec/spec.screen_tracker.rb +211 -0
- data/spec/test_yaml.yml +4 -0
- data/vendor/gocr048.exe +0 -0
- data/zamples/players/captures/hulu full screen non hour.jpg +0 -0
- data/zamples/players/captures/hulu full screen over hour.jpg +0 -0
- data/zamples/players/captures/silence.bmp +0 -0
- data/zamples/players/captures/vlc grab over one hour file over one hour play.bmp +0 -0
- data/zamples/players/captures/vlc2.bmp +0 -0
- data/zamples/players/captures/vlc_full_screen_slider under one hour.bmp +0 -0
- data/zamples/players/captures/youtube full screen big screen.jpg +0 -0
- data/zamples/players/how_to +21 -0
- data/zamples/players/hulu_full_screened_over_an_hour.yml +23 -0
- data/zamples/players/vlc_full_screened.yml +6 -0
- data/zamples/players/vlc_full_screened_over_hour.yml +23 -0
- data/zamples/players/vlc_non_full_screened.yml +19 -0
- data/zamples/players/vlc_non_full_screened_under_an_hour.yml +19 -0
- data/zamples/scene_lists/disney_cars.yml +13 -0
- data/zamples/scene_lists/happy_feet.yml +7 -0
- data/zamples/scene_lists/mute_list.yml +15 -0
- metadata +286 -0
data/FAQ
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
FAQ
|
|
2
|
+
|
|
3
|
+
Q. How can I easily watch this on my TV, not on my computer, silly!
|
|
4
|
+
|
|
5
|
+
A. Currently you'll either need to attach your computer to your TV (buy some long cables, or a new graphics card
|
|
6
|
+
or an adapter cable and some long cords, or get a laptop somehow (ex: buy a used older one) and plug that into your TV.
|
|
7
|
+
|
|
8
|
+
There is also some work working toward getting the stuff playing on your computer to stream live to your wii/ps3/xbox:
|
|
9
|
+
http://betterlogic.com/roger/?p=3023 has the beginnings of said work, though it doesn't work yet, as I have no demo hardware to
|
|
10
|
+
test it out with.
|
|
11
|
+
|
|
12
|
+
A history of thoughts leading up to this can be found here: http://betterlogic.com/roger/?p=2618
|
data/LICENSE
ADDED
data/README
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
This projects aims to allow users to "skip scenes" on media playback. It aims to be be an EDL (http://en.wikipedia.org/wiki/Edit_decision_list) player for any arbitrary player.
|
|
2
|
+
|
|
3
|
+
(VLC and online players, for example hulu/netflix).
|
|
4
|
+
|
|
5
|
+
Trouble Shooting:
|
|
6
|
+
|
|
7
|
+
If you have poor performance, possibly set the process priority to low on the DVD player program. Also report back.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'jeweler'
|
|
2
|
+
require 'os'
|
|
3
|
+
Jeweler::Tasks.new do |s|
|
|
4
|
+
s.name = "sensible-cinema"
|
|
5
|
+
s.summary = "an EDL scene-selector/bleeper that works with online players like hulu"
|
|
6
|
+
s.email = "rogerdpack@gmail.com"
|
|
7
|
+
s.homepage = "http://github.com/rdp"
|
|
8
|
+
s.authors = ["Roger Pack"]
|
|
9
|
+
s.add_development_dependency 'rspec' # prefer rspec 2 I guess...
|
|
10
|
+
s.add_development_dependency 'jeweler'
|
|
11
|
+
s.add_development_dependency 'rdp-rmagick'
|
|
12
|
+
s.add_dependency 'mini_magick' # ocr
|
|
13
|
+
s.add_development_dependency 'hitimes' # now jruby compat. yea!
|
|
14
|
+
s.add_dependency 'sane', '>= 0.22.0'
|
|
15
|
+
s.add_dependency 'rdp-win32screenshot', '>= 0.0.6.2'
|
|
16
|
+
s.extensions = ["ext/mkrf_conf.rb"]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
desc 'run all specs'
|
|
20
|
+
task 'spec' do
|
|
21
|
+
success = true
|
|
22
|
+
for file in Dir['spec/*spec*.rb'] do
|
|
23
|
+
p file
|
|
24
|
+
if !system('cd spec & ' + OS.ruby_bin + " ../" + file)
|
|
25
|
+
success = false
|
|
26
|
+
break
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
p 'all specs passed!' if success
|
|
30
|
+
end
|
data/TODO
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
== medium ==
|
|
2
|
+
|
|
3
|
+
make work with VLC and hulu with hours...
|
|
4
|
+
|
|
5
|
+
== low but actually want to do eventually (me) low prio: just do these...==
|
|
6
|
+
|
|
7
|
+
release ruby-y-y why not, it's interesting
|
|
8
|
+
release it "Linux compat anyone?"
|
|
9
|
+
|
|
10
|
+
just local files for my own edits...
|
|
11
|
+
|
|
12
|
+
== raw backlog ... based on user request.. ==
|
|
13
|
+
|
|
14
|
+
netflix
|
|
15
|
+
|
|
16
|
+
add my own stuff to imdb...
|
|
17
|
+
|
|
18
|
+
imdb parser
|
|
19
|
+
|
|
20
|
+
make it into a real live full functional app...like fully fully functional and good (for use, not editing), mostly with the drop down lists uh guess.
|
|
21
|
+
|
|
22
|
+
GUI: paste edit list, choose player
|
|
23
|
+
|
|
24
|
+
PISH
|
|
25
|
+
|
|
26
|
+
can overlay with a "fuzzer-outer" for specific coordinates somehow or other...
|
|
27
|
+
|
|
28
|
+
advertise like to lay men
|
|
29
|
+
|
|
30
|
+
with VLC non full screen, it does the annoying mouse thing needlessly.
|
|
31
|
+
|
|
32
|
+
hire out scene lists
|
|
33
|
+
|
|
34
|
+
youtube non full screened...hmmm
|
|
35
|
+
|
|
36
|
+
bleeper name
|
|
37
|
+
|
|
38
|
+
yank old gem versions (?) :)
|
|
39
|
+
|
|
40
|
+
overlay with wav file (would work for VLC, could also "click to mute" for the others...)
|
|
41
|
+
|
|
42
|
+
fix pending tests...
|
|
43
|
+
|
|
44
|
+
can black out certain coords to keep things pretty...
|
|
45
|
+
|
|
46
|
+
allow x2,y2 for player descriptions...
|
|
47
|
+
|
|
48
|
+
Linux port (call that good enough for usability on TV's...) between that and a VLC version...
|
|
49
|
+
|
|
50
|
+
a web runnable? Why not?
|
|
51
|
+
click here to watch your favorite film edited!
|
|
52
|
+
|
|
53
|
+
blank out with a user specifiable color (?)
|
|
54
|
+
|
|
55
|
+
Auto mute commercials?
|
|
56
|
+
|
|
57
|
+
rruby.net rubyy.net
|
|
58
|
+
|
|
59
|
+
new github username
|
|
60
|
+
|
|
61
|
+
replay parts
|
|
62
|
+
|
|
63
|
+
overlay/replace with some url of audio or video
|
|
64
|
+
|
|
65
|
+
control volume programmatically (using mouse) on the player itself.
|
|
66
|
+
control mute programmatically (using mouse) on the player itself.
|
|
67
|
+
|
|
68
|
+
overlay alpha transparent pic
|
|
69
|
+
|
|
70
|
+
Have a "list of all known movies (url's)" and be able to open (IE et al) to the correct part, and start playing them, and they work...
|
|
71
|
+
|
|
72
|
+
magnify video parts (?)
|
|
73
|
+
overlay with transparent gif?
|
|
74
|
+
|
|
75
|
+
OCR
|
|
76
|
+
pop it up only every so often (?)
|
|
77
|
+
after commercials?
|
|
78
|
+
|
|
79
|
+
user customizable levels...
|
|
80
|
+
maybe even "I don't like ones that are x, y, z", or "boring level x"
|
|
81
|
+
|
|
82
|
+
user-assignable "confidence" (how much time to 'wrap' surround the mutes, etc. to accomodate for slow computers/laggy internet/different players/poor input)
|
|
83
|
+
|
|
84
|
+
auto-assignment of EDL's to media:
|
|
85
|
+
DVD's
|
|
86
|
+
VLC
|
|
87
|
+
directory of scene-lists
|
|
88
|
+
web plugin?
|
|
89
|
+
|
|
90
|
+
Programmatically do all of the above, by driving a player with its real API.
|
|
91
|
+
VLC
|
|
92
|
+
Allow it to make mp4's somewhere.
|
|
93
|
+
See if burnable to DVD.
|
|
94
|
+
web interface?
|
|
95
|
+
auto start on DVD insertion (?)
|
|
96
|
+
and show appropriate scene-lists available based on title/md5 of something?
|
|
97
|
+
|
|
98
|
+
could have an easy
|
|
99
|
+
|
|
100
|
+
never do unless paid:
|
|
101
|
+
|
|
102
|
+
super easy streamer windows -> {XBOX360, wii, etc..} basically like playon, which appears to have no free equivalent, I guess, though you can
|
|
103
|
+
save the files somewhere and stream them (and stream DVD's [?]) using tversity...maybe some other things...hmm...but no netflix!
|
|
104
|
+
so currently they basically need to run a cable from laptop to PC, for me. windows laptop, for netflix, though a dedicated box could run things like boxee.
|
|
105
|
+
so I could create something that's basically windows -> ??? (ushare).
|
|
106
|
+
For now it's either a cable, a computer (with its cable), or pay.
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.6.0
|
data/bin/bad_digit10.bmp
ADDED
|
Binary file
|
data/bin/bad_digit11.bmp
ADDED
|
Binary file
|
data/bin/bad_digit12.bmp
ADDED
|
Binary file
|
data/bin/bad_digit13.bmp
ADDED
|
Binary file
|
data/bin/bad_digit14.bmp
ADDED
|
Binary file
|
data/bin/bad_digit15.bmp
ADDED
|
Binary file
|
data/bin/bad_digit16.bmp
ADDED
|
Binary file
|
data/bin/bad_digit17.bmp
ADDED
|
Binary file
|
data/bin/bad_digit18.bmp
ADDED
|
Binary file
|
data/bin/bad_digit19.bmp
ADDED
|
Binary file
|
data/bin/bad_digit2.bmp
ADDED
|
Binary file
|
data/bin/bad_digit20.bmp
ADDED
|
Binary file
|
data/bin/bad_digit21.bmp
ADDED
|
Binary file
|
data/bin/bad_digit22.bmp
ADDED
|
Binary file
|
data/bin/bad_digit3.bmp
ADDED
|
Binary file
|
data/bin/bad_digit4.bmp
ADDED
|
Binary file
|
data/bin/bad_digit5.bmp
ADDED
|
Binary file
|
data/bin/bad_digit6.bmp
ADDED
|
Binary file
|
data/bin/bad_digit7.bmp
ADDED
|
Binary file
|
data/bin/bad_digit8.bmp
ADDED
|
Binary file
|
data/bin/bad_digit9.bmp
ADDED
|
Binary file
|
data/bin/hours.bmp
ADDED
|
Binary file
|
data/bin/minute_ones.bmp
ADDED
|
Binary file
|
data/bin/minute_tens.bmp
ADDED
|
Binary file
|
data/bin/scene-skipper
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'sane'
|
|
3
|
+
Thread.abort_on_exception=true
|
|
4
|
+
for file in ['overlayer', 'keyboard_input', 'screen_tracker', 'mouse']
|
|
5
|
+
require_relative '../lib/' + file
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
$VERBOSE = 1 if ARGV.delete('-v')
|
|
9
|
+
$TEST = 1 if ARGV.delete('-t')
|
|
10
|
+
|
|
11
|
+
$stderr.puts 'warning: windows only for crucial parts currently' unless ENV['OS'] == 'Windows_NT'
|
|
12
|
+
|
|
13
|
+
first = ARGV[0]
|
|
14
|
+
|
|
15
|
+
if ARGV.length >= 1 && (File.exist?(first) || first == 'test')
|
|
16
|
+
|
|
17
|
+
if File.exist? first
|
|
18
|
+
overlay = OverLayer.new(first, ARGV[2])
|
|
19
|
+
overlay.start_thread true
|
|
20
|
+
else
|
|
21
|
+
puts 'warning--only doing screen dump in 4s...'
|
|
22
|
+
overlay = nil
|
|
23
|
+
$VERBOSE = 1 # that's what they wanted...
|
|
24
|
+
sleep 4
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if ARGV[1] && File.exist?(ARGV[1])
|
|
28
|
+
# this one doesn't use file updates, so pass it the string
|
|
29
|
+
screen_tracker = ScreenTracker.new_from_yaml File.binread(ARGV[1]), overlay
|
|
30
|
+
screen_tracker.dump_bmp if $VERBOSE
|
|
31
|
+
exit 1 unless overlay
|
|
32
|
+
screen_tracker.process_forever_in_thread
|
|
33
|
+
Mouse.jitter_forever_in_own_thread
|
|
34
|
+
else
|
|
35
|
+
puts 'warning--not using any screen tracking...'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
key_input = KeyboardInput.new overlay
|
|
39
|
+
key_input.start_thread # status thread
|
|
40
|
+
key_input.handle_keystrokes_forever # when this method exits, we want to exit fully...
|
|
41
|
+
|
|
42
|
+
else
|
|
43
|
+
puts <<-END
|
|
44
|
+
|
|
45
|
+
syntax: mute_lists.yml [player_description.yml] [-v (verbose [chatty] mode)] [-t (test mode)]
|
|
46
|
+
See the #{File.expand_path(File.dirname(__FILE__), "..")}/zamples for more info on creating files.
|
|
47
|
+
END
|
|
48
|
+
|
|
49
|
+
for file in Dir[__dir__ + '../zamples/mute*/*']
|
|
50
|
+
puts "\n", "Example file:", file + "\n\n", File.read(file)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
puts '', 'Available files:'
|
|
54
|
+
for file in Dir[__dir__ + '../zamples/*/*']
|
|
55
|
+
puts File.expand_path(file) unless File.directory?(file)
|
|
56
|
+
end
|
|
57
|
+
exit 1
|
|
58
|
+
end
|
data/bin/second_ones.bmp
ADDED
|
Binary file
|
data/bin/second_tens.bmp
ADDED
|
Binary file
|
data/ext/mkrf_conf.rb
ADDED
data/lib/blanker.rb
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
class Blanker
|
|
4
|
+
|
|
5
|
+
if RUBY_PLATFORM =~ /java/
|
|
6
|
+
require 'java'
|
|
7
|
+
JFrame = javax.swing.JFrame
|
|
8
|
+
JPanel = javax.swing.JPanel
|
|
9
|
+
|
|
10
|
+
def self.blank_full_screen!
|
|
11
|
+
# a new screen each time as other jruby doesn't terminate as gracefully as we would like...
|
|
12
|
+
frame = JFrame.new("Edited!") # ltodo take out...
|
|
13
|
+
frame.default_close_operation = JFrame::EXIT_ON_CLOSE
|
|
14
|
+
frame.set_location(0,0)
|
|
15
|
+
frame.set_size(2000, 2000) # ltodo better coords...
|
|
16
|
+
frame.show
|
|
17
|
+
# lodo on top?
|
|
18
|
+
|
|
19
|
+
fr = frame
|
|
20
|
+
fr.set_resizable(false)
|
|
21
|
+
|
|
22
|
+
fr.set_undecorated(true) unless fr.is_displayable
|
|
23
|
+
|
|
24
|
+
# probably unnecessary
|
|
25
|
+
panel = JPanel.new
|
|
26
|
+
frame.add(panel)
|
|
27
|
+
# frame.set_background()
|
|
28
|
+
panel.repaint
|
|
29
|
+
panel.revalidate
|
|
30
|
+
# too heavy!
|
|
31
|
+
# gd = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
|
|
32
|
+
# gd.set_full_screen_window(fr)
|
|
33
|
+
@fr = fr
|
|
34
|
+
@fr.set_visible(true)
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
|
|
38
|
+
def self.blank_full_screen!
|
|
39
|
+
puts 'the screen is now...blank!'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.unblank_full_screen!
|
|
45
|
+
if RUBY_PLATFORM =~ /java/
|
|
46
|
+
if @fr
|
|
47
|
+
@fr.dispose
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
puts 'the screen is now...visible!'
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'sane'
|
|
3
|
+
require 'Win32API'
|
|
4
|
+
|
|
5
|
+
# does the jruby check inline
|
|
6
|
+
|
|
7
|
+
class KeyboardInput
|
|
8
|
+
|
|
9
|
+
def initialize fella
|
|
10
|
+
@fella = fella
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def start_thread
|
|
14
|
+
Thread.new { loop {
|
|
15
|
+
print get_line_printout
|
|
16
|
+
sleep 0.1
|
|
17
|
+
} }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def get_line_printout
|
|
21
|
+
status = @fella.status
|
|
22
|
+
# scary hard coded values here...
|
|
23
|
+
" " * 20 + "\b"*150 + status
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def getch
|
|
27
|
+
@getch ||= Win32API.new('crtdll', '_getch', [], 'L')
|
|
28
|
+
@getch.call
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def handle_keystrokes_forever
|
|
32
|
+
raise 'only jruby supported, as it looks just too messy in normal ruby' unless OS.java?
|
|
33
|
+
while(ch = getch)
|
|
34
|
+
return if ch.in? [3, 113] # ctrl+c, q -> exit
|
|
35
|
+
# lodo handle arrow keys, too, which is a bit more complicated...
|
|
36
|
+
handle_keystroke ch
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def handle_keystroke ch
|
|
41
|
+
string = "" << ch
|
|
42
|
+
@fella.keyboard_input(string)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
data/lib/mouse.rb
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'ffi'
|
|
3
|
+
|
|
4
|
+
module Mouse
|
|
5
|
+
extend FFI::Library
|
|
6
|
+
|
|
7
|
+
ffi_lib 'user32'
|
|
8
|
+
ffi_convention :stdcall
|
|
9
|
+
|
|
10
|
+
MOUSEEVENTF_MOVE = 1
|
|
11
|
+
INPUT_MOUSE = 0
|
|
12
|
+
MOUSEEVENTF_ABSOLUTE = 0x8000
|
|
13
|
+
|
|
14
|
+
class MouseInput < FFI::Struct
|
|
15
|
+
layout :dx, :long,
|
|
16
|
+
:dy, :long,
|
|
17
|
+
:mouse_data, :ulong,
|
|
18
|
+
:flags, :ulong,
|
|
19
|
+
:time, :ulong,
|
|
20
|
+
:extra, :ulong
|
|
21
|
+
end
|
|
22
|
+
class InputEvent < FFI::Union
|
|
23
|
+
layout :mi, MouseInput
|
|
24
|
+
end
|
|
25
|
+
class Input < FFI::Struct
|
|
26
|
+
layout :type, :ulong,
|
|
27
|
+
:evt, InputEvent
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# UINT SendInput(UINT nInputs, LPINPUT pInputs, int cbSize);
|
|
31
|
+
attach_function :SendInput, [ :uint, :pointer, :int ], :uint
|
|
32
|
+
|
|
33
|
+
def self.jitter_forever_in_own_thread
|
|
34
|
+
|
|
35
|
+
myinput = Mouse::Input.new
|
|
36
|
+
myinput[:type] = Mouse::INPUT_MOUSE
|
|
37
|
+
|
|
38
|
+
in_evt = myinput[:evt][:mi]
|
|
39
|
+
|
|
40
|
+
in_evt[:mouse_data] = 0
|
|
41
|
+
in_evt[:flags] = Mouse::MOUSEEVENTF_MOVE # | Mouse::MOUSEEVENTF_ABSOLUTE
|
|
42
|
+
in_evt[:time] = 0
|
|
43
|
+
in_evt[:extra] = 0
|
|
44
|
+
in_evt[:dx] = 0
|
|
45
|
+
in_evt[:dy] = 8 # just enough for VLC full screen...
|
|
46
|
+
|
|
47
|
+
Thread.new {
|
|
48
|
+
loop {
|
|
49
|
+
in_evt[:dy] *= -1
|
|
50
|
+
Mouse.SendInput(1, myinput, Mouse::Input.size)
|
|
51
|
+
in_evt[:dy] *= -1
|
|
52
|
+
sleep 0.05
|
|
53
|
+
Mouse.SendInput(1, myinput, Mouse::Input.size)
|
|
54
|
+
sleep 0.75
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
data/lib/muter.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'rubygems' # ugh
|
|
2
|
+
require 'ffi'
|
|
3
|
+
|
|
4
|
+
module Muter
|
|
5
|
+
# from msdn on keybd_event ...
|
|
6
|
+
|
|
7
|
+
VK_VOLUME_DOWN = 0xAE
|
|
8
|
+
VK_VOLUME_UP = 0xAF
|
|
9
|
+
VK_VOLUME_MUTE = 0xAD
|
|
10
|
+
KEYEVENTF_KEYUP = 2
|
|
11
|
+
|
|
12
|
+
extend FFI::Library
|
|
13
|
+
ffi_lib 'user32'
|
|
14
|
+
ffi_convention :stdcall
|
|
15
|
+
|
|
16
|
+
attach_function :keybd_event, [ :uchar, :uchar, :int, :pointer ], :void
|
|
17
|
+
|
|
18
|
+
def hit_mute_key
|
|
19
|
+
# simulate pressing the mute key
|
|
20
|
+
keybd_event(VK_VOLUME_MUTE, 0, 0, nil)
|
|
21
|
+
keybd_event(VK_VOLUME_MUTE, 0, KEYEVENTF_KEYUP, nil)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def hit_volume_up_key
|
|
25
|
+
keybd_event(VK_VOLUME_UP, 0, 0, nil)
|
|
26
|
+
keybd_event(VK_VOLUME_UP, 0, KEYEVENTF_KEYUP, nil)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def hit_volume_down_key
|
|
30
|
+
keybd_event(VK_VOLUME_DOWN, 0, 0, nil)
|
|
31
|
+
keybd_event(VK_VOLUME_DOWN, 0, KEYEVENTF_KEYUP, nil)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def mute!
|
|
35
|
+
#unmute! # just in case
|
|
36
|
+
hit_mute_key
|
|
37
|
+
end
|
|
38
|
+
# TODO better for 7...
|
|
39
|
+
def unmute!
|
|
40
|
+
hit_mute_key # Windows XP...
|
|
41
|
+
hit_volume_down_key
|
|
42
|
+
hit_volume_up_key
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# allow for Muter.xxx
|
|
46
|
+
extend self
|
|
47
|
+
|
|
48
|
+
end
|
data/lib/ocr.rb
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'mini_magick'
|
|
2
|
+
require 'open3'
|
|
3
|
+
|
|
4
|
+
# helper for OCR'ing single digits that were screen captured
|
|
5
|
+
module OCR
|
|
6
|
+
|
|
7
|
+
GOCR = File.expand_path(File.dirname(__FILE__) + "/../vendor/gocr048.exe -C 0-9:/ ")
|
|
8
|
+
|
|
9
|
+
CACHE = {}
|
|
10
|
+
|
|
11
|
+
# options are :might_be_colon, :should_invert
|
|
12
|
+
def identify_digit memory_bitmap, options = {}
|
|
13
|
+
if CACHE[memory_bitmap]
|
|
14
|
+
print 'h' if $DEBUG
|
|
15
|
+
return CACHE[memory_bitmap]
|
|
16
|
+
else
|
|
17
|
+
p 'ocr cache miss' if $DEBUG
|
|
18
|
+
end
|
|
19
|
+
might_be_colon = options[:might_be_colon]
|
|
20
|
+
should_invert = options[:should_invert]
|
|
21
|
+
if might_be_colon
|
|
22
|
+
# do processing in-line <sigh>
|
|
23
|
+
total = (memory_bitmap.scan /\x00{5}+/).length
|
|
24
|
+
if total >= 3 # really should be 4 for VLC
|
|
25
|
+
# it had some dots...must have been a colon!
|
|
26
|
+
end
|
|
27
|
+
CACHE[memory_bitmap] = ":"
|
|
28
|
+
return ":"
|
|
29
|
+
end
|
|
30
|
+
image = MiniMagick::Image.from_blob(memory_bitmap)
|
|
31
|
+
image.format(:pnm) # expensive, requires convert.exe in path...
|
|
32
|
+
if should_invert # mogrify calls it negate...
|
|
33
|
+
image.negate
|
|
34
|
+
end
|
|
35
|
+
for level in [130, 100] # 100 for hulu...
|
|
36
|
+
input, output, error, thread_if_on_19 = Open3.popen3 GOCR + " -l #{level} -"
|
|
37
|
+
input.write image.to_blob
|
|
38
|
+
input.close
|
|
39
|
+
a = output.read
|
|
40
|
+
output.close
|
|
41
|
+
a.strip!
|
|
42
|
+
if a =~ /[0-9]/
|
|
43
|
+
a = a.to_i
|
|
44
|
+
CACHE[memory_bitmap] = a
|
|
45
|
+
return a
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def version
|
|
52
|
+
`#{GOCR} -h 2>&1`
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
extend self
|
|
56
|
+
|
|
57
|
+
end
|