sensible-cinema 0.28.0 → 0.28.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/LICENSE.TXT +1 -1
  2. data/README +6 -4
  3. data/Rakefile +41 -24
  4. data/TODO +41 -10
  5. data/VERSION +1 -1
  6. data/change_log_with_feature_list.txt +12 -0
  7. data/documentation/is_it_legal_to_copy_dvds.txt +4 -2
  8. data/go +1 -0
  9. data/goc +1 -0
  10. data/history_and_related_works_list.txt +2 -0
  11. data/inventionzy_files/control_youtube.html +135 -0
  12. data/inventionzy_files/md5s.txt +53 -0
  13. data/inventionzy_files/play_with_inserted_scene.bat +8 -0
  14. data/inventionzy_files/play_with_overlay.bat +24 -0
  15. data/inventionzy_files/serve.rb +6 -0
  16. data/inventionzy_files/transcript_mute_vlc.txt +117 -0
  17. data/lib/add_any_bundled_gems_to_load_path.rb +1 -1
  18. data/lib/edl_parser.rb +2 -0
  19. data/lib/gui/sensible-cinema-base.rb +10 -68
  20. data/lib/gui/sensible-cinema-create.rb +16 -10
  21. data/lib/gui/sensible-cinema-dependencies.rb +1 -0
  22. data/lib/gui/sensible-cinema-normal.rb +11 -14
  23. data/lib/muter.rb +1 -1
  24. data/lib/subtitle_profanity_finder.rb +3 -2
  25. data/spec/notes +2 -0
  26. data/template_bats/README_DISTRO.TXT +6 -0
  27. data/template_bats/mac/RUN SENSIBLE CINEMA CLICK HERE.sh b/data/template_bats/mac/RUN SENSIBLE CINEMA CLICK → HERE.command +0 -0
  28. data/template_bats/mac/{advanced--create or edit sensible cinema edit list files.sh → advanced--create or edit sensible cinema edit list files.command } +1 -0
  29. data/template_bats/mac/{advanced--run-upconverting-video-player.sh → advanced--run-upconverting-video-player.command} +1 -0
  30. data/todo.inventionzy.txt +11 -0
  31. data/todo.propaganda +21 -18
  32. data/vendor/rdp-win32screenshot-0.0.9/.document +5 -0
  33. data/vendor/rdp-win32screenshot-0.0.9/History.rdoc +53 -0
  34. data/vendor/rdp-win32screenshot-0.0.9/LICENSE +20 -0
  35. data/vendor/rdp-win32screenshot-0.0.9/RDP_BRANCH_HAS_MASTER_WITH_CORRECT_VERSION_NUMBER +0 -0
  36. data/vendor/rdp-win32screenshot-0.0.9/RDP_VERSION_IS_IN_RDP_BRANCH +0 -0
  37. data/vendor/rdp-win32screenshot-0.0.9/README.rdoc +95 -0
  38. data/vendor/rdp-win32screenshot-0.0.9/Rakefile +63 -0
  39. data/vendor/rdp-win32screenshot-0.0.9/VERSION +1 -0
  40. data/vendor/rdp-win32screenshot-0.0.9/enumerated +55576 -0
  41. data/vendor/rdp-win32screenshot-0.0.9/lib/aero_offscreen_srccopy_captureblt_doesnt_have_everything.bmp.gz +0 -0
  42. data/vendor/rdp-win32screenshot-0.0.9/lib/enumerate.rb +6 -0
  43. data/vendor/rdp-win32screenshot-0.0.9/lib/firefox.bmp +0 -0
  44. data/vendor/rdp-win32screenshot-0.0.9/lib/normal.bmp +0 -0
  45. data/vendor/rdp-win32screenshot-0.0.9/lib/normal2.bmp +0 -0
  46. data/vendor/rdp-win32screenshot-0.0.9/lib/notes +5 -0
  47. data/vendor/rdp-win32screenshot-0.0.9/lib/snapshot.rb +10 -0
  48. data/vendor/rdp-win32screenshot-0.0.9/lib/srccopy.bmp +0 -0
  49. data/vendor/rdp-win32screenshot-0.0.9/lib/srccopyplus.bmp +0 -0
  50. data/vendor/rdp-win32screenshot-0.0.9/lib/srccopyplusdirectx.bmp +0 -0
  51. data/vendor/rdp-win32screenshot-0.0.9/lib/vc.bmp +0 -0
  52. data/vendor/rdp-win32screenshot-0.0.9/lib/win32/screenshot.rb +95 -0
  53. data/vendor/rdp-win32screenshot-0.0.9/lib/win32/screenshot/bitmap_maker.rb +200 -0
  54. data/vendor/rdp-win32screenshot-0.0.9/lib/win32/util.rb +93 -0
  55. data/vendor/rdp-win32screenshot-0.0.9/spec/spec.opts +1 -0
  56. data/vendor/rdp-win32screenshot-0.0.9/spec/spec_helper.rb +85 -0
  57. data/vendor/rdp-win32screenshot-0.0.9/spec/win32_screenshot_spec.rb +194 -0
  58. data/vendor/rdp-win32screenshot-0.0.9/spec/win32_screenshot_util_spec.rb +75 -0
  59. data/vendor/rdp-win32screenshot-0.0.9/win32screenshot.gemspec +69 -0
  60. data/{subfont.ttf → vendor/subfont.ttf} +0 -0
  61. data/zamples/edit_decision_lists/dvds/{edls_being_edited/cars_disney.txt → cars_disney.txt} +0 -0
  62. data/zamples/edit_decision_lists/dvds/edls_being_edited/king_of_kings.txt +28 -0
  63. data/zamples/edit_decision_lists/dvds/monsters_vs_aliens.txt +41 -0
  64. data/zamples/edit_decision_lists/dvds/peter_pan.txt +29 -0
  65. data/zamples/edit_decision_lists/dvds/speed_racer.txt +47 -0
  66. data/zamples/edit_decision_lists/notes/tron.txt +4 -0
  67. metadata +77 -54
  68. data/go.sh +0 -1
  69. data/legal2 +0 -3
  70. data/lib/play_audio.rb +0 -58
  71. data/lib/ruby_clip.rb +0 -26
  72. data/template_bats/RUN SENSIBLE CINEMA CLICK HERE.bat +0 -25
  73. data/template_bats/advanced--create or edit sensible cinema edit list files.bat +0 -1
  74. data/template_bats/advanced--run-upconverting-video-player.bat +0 -1
  75. data/transparent.png +0 -0
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require './lib/win32/screenshot'
3
+ require 'pp'
4
+ sleep 3
5
+ p 'enumerating'
6
+ pp Win32::Screenshot::Util.windows_hierarchy true
@@ -0,0 +1,5 @@
1
+ without aero
2
+ Win32::Screenshot.window( /virtual/i, 0) {|h,w,bits| File.binwrite('1' +name, bits)}
3
+ was "cropped" and probably had to come to the front, but was full.
4
+
5
+ with aero, it didn't show everything [!] so I guess it's really just grabbing that window via hwnd.
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require './win32/screenshot'
3
+ require 'sane'
4
+ #sleep 2
5
+ p 'taking it'
6
+ #p Win32::Screenshot::BitmapMaker.hwnd(/virtual/i).to_s(16)
7
+ name = ARGV[0] || 'out.bmp'
8
+ Win32::Screenshot::BitmapMaker.capture_area( Win32::Screenshot::BitmapMaker.hwnd(/virtual/i), 0,0,1000,1000) {|h,w,bits| File.binwrite(name, bits)}
9
+ Win32::Screenshot.window( /virtual/i, 0) {|h,w,bits| File.binwrite('1' +name, bits)}
10
+ p name
@@ -0,0 +1,95 @@
1
+ require File.dirname(__FILE__) + '/screenshot/bitmap_maker'
2
+ require File.dirname(__FILE__) + '/util'
3
+
4
+ module Win32
5
+ # Captures screenshots with Ruby on Windows
6
+ class Screenshot
7
+ class << self
8
+
9
+ # captures foreground
10
+ def foreground(&proc)
11
+ hwnd = BitmapMaker.foreground_window
12
+ BitmapMaker.capture_all(hwnd, &proc)
13
+ end
14
+
15
+ # captures area of the foreground
16
+ # where *x1* and *y1* are 0 in the upper left corner and
17
+ # *x2* specifies the width and *y2* the height of the area to be captured
18
+ def foreground_area(x1, y1, x2, y2, &proc)
19
+ hwnd = BitmapMaker.foreground_window
20
+ validate_coordinates(hwnd, x1, y1, x2, y2)
21
+ BitmapMaker.capture_area(hwnd, x1, y1, x2, y2, &proc)
22
+ end
23
+
24
+ # captures visible view of the screen
25
+ #
26
+ # to make screenshot of the real desktop, all
27
+ # windows must be minimized before
28
+ def desktop(&proc)
29
+ hwnd = BitmapMaker.desktop_window
30
+ BitmapMaker.capture_all(hwnd, &proc)
31
+ end
32
+
33
+ # captures area of the visible view of the screen
34
+ # where *x1* and *y1* are 0 in the upper left corner and
35
+ # *x2* specifies the width and *y2* the height of the area to be captured
36
+ #
37
+ # to make screenshot of the real desktop, all
38
+ # windows must be minimized before
39
+ def desktop_area(x1, y1, x2, y2, &proc)
40
+ hwnd = BitmapMaker.desktop_window
41
+ validate_coordinates(hwnd, x1, y1, x2, y2)
42
+ BitmapMaker.capture_area(hwnd, x1, y1, x2, y2, &proc)
43
+ end
44
+
45
+ # captures window with a *title_query* and waits *pause* (by default is 0.5)
46
+ # seconds after trying to set window to the foreground
47
+ def window(title_query, pause=0.5, &proc)
48
+ hwnd = Util.window_hwnd(title_query)
49
+ hwnd(hwnd, pause, &proc)
50
+ end
51
+
52
+ # captures area of the window with a *title_query*
53
+ # where *x1* and *y1* are 0 in the upper left corner and
54
+ # *x2* specifies the width and *y2* the height of the area to be captured
55
+ def window_area(title_query, x1, y1, x2, y2, pause=0.5, &proc)
56
+ hwnd = Util.window_hwnd(title_query)
57
+ hwnd_area(hwnd, x1, y1, x2, y2, pause, &proc)
58
+ end
59
+
60
+ # captures by window handle
61
+ def hwnd(hwnd, pause=0.5, &proc)
62
+ BitmapMaker.prepare_window(hwnd, pause)
63
+ BitmapMaker.capture_all(hwnd, &proc)
64
+ end
65
+
66
+ # captures area of the window with a handle of *hwnd*
67
+ # where *x1* and *y1* are 0 in the upper left corner and
68
+ # *x2* specifies the width and *y2* the height of the area to be captured
69
+ def hwnd_area(hwnd, x1, y1, x2, y2, pause=0.5, &proc)
70
+ validate_coordinates(hwnd, x1, y1, x2, y2)
71
+ BitmapMaker.prepare_window(hwnd, pause)
72
+ BitmapMaker.capture_area(hwnd, x1, y1, x2, y2, &proc)
73
+ end
74
+
75
+ private
76
+
77
+ def validate_coordinates(hwnd, *coords)
78
+ specified_coordinates = coords.join(', ')
79
+ if coords.any? {|c| c < 0}
80
+ raise "specified coordinates (#{specified_coordinates}) are invalid - cannot be negative!"
81
+ end
82
+ x1, y1, x2, y2 = *coords
83
+ if x1 >= x2 || y1 >= y2
84
+ raise "specified coordinates (#{specified_coordinates}) are invalid - cannot have x1 > x2 or y1 > y2!"
85
+ end
86
+
87
+ max_width, max_height = Util.dimensions_for(hwnd)
88
+ if x2 > max_width || y2 > max_height
89
+ raise "specified coordinates (#{specified_coordinates}) are invalid - maximum are x2=#{max_width} and y2=#{max_height}!"
90
+ end
91
+ end
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,200 @@
1
+ require 'ffi'
2
+
3
+ module Win32
4
+ class Screenshot
5
+ # internal methods
6
+ class BitmapMaker #:nodoc:all
7
+ class << self
8
+ extend FFI::Library
9
+
10
+ ffi_lib 'user32', 'gdi32'
11
+ ffi_convention :stdcall
12
+ callback :enum_callback, [:long, :pointer], :bool
13
+
14
+ # user32.dll
15
+ attach_function :enum_windows, :EnumWindows,
16
+ [:enum_callback, :pointer], :int
17
+ attach_function :enum_child_windows, :EnumChildWindows,
18
+ [:long, :enum_callback, :pointer], :int
19
+ attach_function :window_text, :GetWindowTextA,
20
+ [:long, :pointer, :int], :int
21
+ attach_function :window_text_length, :GetWindowTextLengthA,
22
+ [:long], :int
23
+ attach_function :class_name, :GetClassNameA,
24
+ [:long, :pointer, :int], :int
25
+ attach_function :window_visible, :IsWindowVisible,
26
+ [:long], :bool
27
+ attach_function :dc, :GetDC,
28
+ [:long], :long
29
+ attach_function :client_rect, :GetClientRect,
30
+ [:long, :pointer], :bool
31
+ attach_function :window_rect, :GetWindowRect,
32
+ [:long, :pointer], :bool
33
+ attach_function :minimized, :IsIconic,
34
+ [:long], :bool
35
+ attach_function :show_window, :ShowWindow,
36
+ [:long, :int], :bool
37
+ attach_function :foreground_window, :GetForegroundWindow,
38
+ [], :long
39
+ attach_function :desktop_window, :GetDesktopWindow,
40
+ [], :long
41
+ attach_function :window_thread_process_id, :GetWindowThreadProcessId,
42
+ [:long, :pointer], :long
43
+ attach_function :attach_thread_input, :AttachThreadInput,
44
+ [:long, :long, :bool], :bool
45
+ attach_function :set_foreground_window, :SetForegroundWindow,
46
+ [:long], :bool
47
+ attach_function :bring_window_to_top, :BringWindowToTop,
48
+ [:long], :bool
49
+ attach_function :set_active_window, :SetActiveWindow,
50
+ [:long], :long
51
+ attach_function :GetWindowThreadProcessId, [:ulong, :pointer],
52
+ :uint
53
+
54
+ # gdi32.dll
55
+ attach_function :create_compatible_dc, :CreateCompatibleDC,
56
+ [:long], :long
57
+ attach_function :create_compatible_bitmap, :CreateCompatibleBitmap,
58
+ [:long, :int, :int], :long
59
+ attach_function :select_object, :SelectObject,
60
+ [:long, :long], :long
61
+ attach_function :bit_blt, :BitBlt,
62
+ [:long, :int, :int, :int, :int, :long, :int, :int, :long], :bool
63
+ attach_function :di_bits, :GetDIBits,
64
+ [:long, :long, :int, :int, :pointer, :pointer, :int], :int
65
+ attach_function :delete_object, :DeleteObject,
66
+ [:long], :bool
67
+ attach_function :delete_dc, :DeleteDC,
68
+ [:long], :bool
69
+ attach_function :release_dc, :ReleaseDC,
70
+ [:long, :long], :int
71
+
72
+
73
+ EnumWindowCallback = FFI::Function.new(:bool, [ :long, :pointer ], { :convention => :stdcall }) do |hwnd, param|
74
+ searched_window = WindowStruct.new param
75
+ if(searched_window[:search_class] != 0)
76
+ title = Util.window_class(hwnd)
77
+ else
78
+ title = Util.window_title(hwnd)
79
+ end
80
+ if title =~ Regexp.new(searched_window[:title].read_string) && window_visible(hwnd)
81
+ searched_window[:hwnd] = hwnd
82
+ false
83
+ else
84
+ if(searched_window[:search_class] != 0)
85
+ # if they're searching for a classname, enumerate children, too
86
+ enum_child_windows(hwnd, EnumWindowCallback, param)
87
+ if searched_window[:hwnd] != 0
88
+ # return early if already discovered
89
+ false
90
+ else
91
+ true
92
+ end
93
+ else
94
+ true
95
+ end
96
+ end
97
+ end
98
+
99
+ class WindowStruct < FFI::Struct
100
+ layout :title, :pointer,
101
+ :hwnd, :long,
102
+ :search_class, :char # boolean
103
+ end
104
+
105
+ def hwnd(window_title, search_class = false)
106
+ window = WindowStruct.new
107
+ unless window_title.is_a?(Regexp)
108
+ window_title = Regexp.escape(window_title.to_s)
109
+ else
110
+ window_title = window_title.to_s
111
+ end
112
+ window_title = FFI::MemoryPointer.from_string(window_title)
113
+ window[:title] = window_title
114
+ window[:search_class] = search_class ? 1 : 0
115
+ enum_windows(EnumWindowCallback, window.to_ptr)
116
+ window[:hwnd] == 0 ? nil : window[:hwnd]
117
+ end
118
+
119
+ def prepare_window(hwnd, pause)
120
+ restore(hwnd) if minimized(hwnd)
121
+ set_foreground(hwnd)
122
+ sleep pause
123
+ end
124
+
125
+ SW_RESTORE = 9
126
+
127
+ def restore(hwnd)
128
+ show_window(hwnd, SW_RESTORE)
129
+ end
130
+
131
+ def set_foreground(hwnd)
132
+ if foreground_window != hwnd
133
+ set_foreground_window(hwnd)
134
+ set_active_window(hwnd)
135
+ bring_window_to_top(hwnd)
136
+ # and just in case...
137
+ foreground_thread = window_thread_process_id(foreground_window, nil)
138
+ other_thread = window_thread_process_id(hwnd, nil)
139
+ attach_thread_input(foreground_thread, other_thread, true) unless other_thread == foreground_thread
140
+ set_foreground_window(hwnd)
141
+ set_active_window(hwnd)
142
+ bring_window_to_top(hwnd)
143
+ attach_thread_input(foreground_thread, other_thread, false) unless other_thread == foreground_thread
144
+ end
145
+ end
146
+
147
+ def get_process_id_from_hwnd hwnd
148
+ out = FFI::MemoryPointer.new(:uint)
149
+ GetWindowThreadProcessId(hwnd, out)
150
+ out.get_uint32(0) # read_uint
151
+ end
152
+
153
+ def capture_all(hwnd, &proc)
154
+ width, height = Util.dimensions_for(hwnd)
155
+ capture_area(hwnd, 0, 0, width, height, &proc)
156
+ end
157
+
158
+ SRCCOPY = 0x00CC0020
159
+ CAPTUREBLT = 0x40000000 #0x40000000
160
+ DIB_RGB_COLORS = 0
161
+
162
+ def capture_area(hwnd, x1, y1, x2, y2) # block
163
+ hScreenDC = dc(hwnd)
164
+ w = x2-x1
165
+ h = y2-y1
166
+
167
+ hmemDC = create_compatible_dc(hScreenDC)
168
+ hmemBM = create_compatible_bitmap(hScreenDC, w, h)
169
+ select_object(hmemDC, hmemBM)
170
+ # p (SRCCOPY|CAPTUREBLT).to_s(16), 'hello'
171
+ bit_blt(hmemDC, 0, 0, w, h, hScreenDC, x1, y1, SRCCOPY)
172
+ bitmap_size = w * h * 3 + w % 4 * h # assumes 24 bit, funky math LOL
173
+ lpvpxldata = FFI::MemoryPointer.new(bitmap_size)
174
+
175
+ # Bitmap header
176
+ # http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html
177
+ bmInfo = [40, w, h, 1, 24, 0, 0, 0, 0, 0, 0, 0].pack('L3S2L6')
178
+ di_bits(hmemDC, hmemBM, 0, h, lpvpxldata, bmInfo, DIB_RGB_COLORS) # converts to 24 bit here...
179
+
180
+ bmFileHeader = [
181
+ 19778,
182
+ bitmap_size + 40 + 14,
183
+ 0,
184
+ 0,
185
+ 54
186
+ ].pack('SLSSL')
187
+ p 'header length', bmFileHeader.size, 'info length', bmInfo.size, 'data length', lpvpxldata.read_string(bitmap_size).length
188
+ bmp_data = bmFileHeader + bmInfo + lpvpxldata.read_string(bitmap_size)
189
+ p 'total', bmp_data.size
190
+ yield(w, h, bmp_data)
191
+ ensure
192
+ lpvpxldata.free
193
+ delete_object(hmemBM)
194
+ delete_dc(hmemDC)
195
+ release_dc(0, hScreenDC)
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,93 @@
1
+ module Win32
2
+ class Screenshot
3
+ class Util
4
+ class << self
5
+
6
+ def all_desktop_windows
7
+ titles = []
8
+ window_callback = FFI::Function.new(:bool, [ :long, :pointer ], { :convention => :stdcall }) do |hwnd, param|
9
+ titles << [window_title(hwnd), hwnd]
10
+ true
11
+ end
12
+
13
+ BitmapMaker.enum_windows(window_callback, nil)
14
+ titles
15
+ end
16
+
17
+ # just returns a long list of hwnd's...
18
+ # unless with_info is true
19
+ # then it will return all hwnds with full info about each window
20
+ def windows_hierarchy with_info = false
21
+ all = {}
22
+ desktop_hwnd = BitmapMaker.desktop_window
23
+ root = {:hwnd => desktop_hwnd, :children => []}
24
+ root.merge!(get_info(desktop_hwnd)) if with_info
25
+ parents = []
26
+ parents << root
27
+ window_callback = FFI::Function.new(:bool, [ :long, :pointer ], { :convention => :stdcall }) do |hwnd, param|
28
+ # this is a child of the most recent parent
29
+ myself = {:hwnd => hwnd, :children => []}
30
+ myself.merge!(get_info(hwnd)) if with_info
31
+ parents[-1][:children] << myself
32
+ parents << myself
33
+ if !all[hwnd]
34
+ all[hwnd] = true
35
+ BitmapMaker.enum_child_windows(hwnd, window_callback, nil)
36
+ end
37
+
38
+ parents.pop
39
+ true
40
+ end
41
+ BitmapMaker.enum_child_windows(desktop_hwnd, window_callback, nil)
42
+ root
43
+ end
44
+
45
+ def get_info hwnd
46
+ {:title => window_title(hwnd),
47
+ :class => window_class(hwnd),
48
+ :dimensions => dimensions_for(hwnd),
49
+ :starting_coordinates => location_of(hwnd)
50
+ }
51
+ end
52
+
53
+ def window_title hwnd
54
+ title_length = BitmapMaker.window_text_length(hwnd) + 1
55
+ title = FFI::MemoryPointer.new :char, title_length
56
+ BitmapMaker.window_text(hwnd, title, title_length)
57
+ title.read_string
58
+ end
59
+
60
+ def window_class hwnd
61
+ title = FFI::MemoryPointer.new :char, 100
62
+ BitmapMaker.class_name(hwnd, title, 99)
63
+ title.read_string
64
+ end
65
+
66
+ def window_hwnd(title_query)
67
+ hwnd = BitmapMaker.hwnd(title_query)
68
+ raise "window with title '#{title_query}' was not found!" unless hwnd
69
+ hwnd
70
+ end
71
+
72
+ def location_of(hwnd)
73
+ rect = [0, 0, 0, 0].pack('L4')
74
+ BitmapMaker.window_rect(hwnd, rect)
75
+ x, y, width, height = rect.unpack('L4')
76
+ return x, y
77
+ end
78
+
79
+ def dimensions_for(hwnd)
80
+ rect = [0, 0, 0, 0].pack('L4')
81
+ BitmapMaker.client_rect(hwnd, rect)
82
+ _, _, width, height = rect.unpack('L4')
83
+ return width, height
84
+ end
85
+
86
+ def window_process_id(hwnd)
87
+ BitmapMaker.get_process_id_from_hwnd(hwnd)
88
+ end
89
+
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,85 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'win32/screenshot'
4
+ require 'rubygems'
5
+ require 'spec'
6
+ require 'spec/autorun'
7
+ require 'RMagick'
8
+ require 'fileutils'
9
+
10
+ module SpecHelper
11
+ SW_MAXIMIZE = 3
12
+ SW_MINIMIZE = 6
13
+ HWND_TOPMOST = -1
14
+ HWND_NOTOPMOST = -2
15
+ SWP_NOSIZE = 1
16
+ SWP_NOMOVE = 2
17
+ SWP_SHOWWINDOW = 40
18
+
19
+ extend FFI::Library
20
+ ffi_lib 'user32'
21
+ ffi_convention :stdcall
22
+
23
+ # user32.dll
24
+ attach_function :set_window_pos, :SetWindowPos,
25
+ [:long, :long, :int, :int, :int, :int, :int], :bool
26
+
27
+ def cleanup
28
+ FileUtils.rm Dir.glob(File.join(File.dirname(__FILE__), "tmp/*"))
29
+ end
30
+
31
+ def check_image(bmp, file=nil)
32
+ temp_dir = File.join(File.dirname(__FILE__), 'tmp')
33
+ FileUtils.mkdir temp_dir unless File.exists?(temp_dir)
34
+ File.open(File.join(temp_dir, "#{file}.bmp"), "wb") {|io| io.write(bmp)} unless file.nil?
35
+ bmp[0..1].should == 'BM'
36
+ img = Magick::Image.from_blob(bmp)
37
+ png = img[0].to_blob {self.format = 'PNG'}
38
+ png[0..3].should == "\211PNG"
39
+ File.open(File.join(temp_dir, "#{file}.png"), "wb") {|io| io.puts(png)} unless file.nil?
40
+ end
41
+
42
+ def wait_for_programs_to_open
43
+ until Win32::Screenshot::BitmapMaker.hwnd(/Internet Explorer/) &&
44
+ Win32::Screenshot::BitmapMaker.hwnd(/Notepad/)
45
+ sleep 0.1
46
+ end
47
+ wait_for_calculator_to_open
48
+
49
+ # just in case of slow PC
50
+ sleep 8
51
+ end
52
+
53
+ def wait_for_calculator_to_open
54
+ until Win32::Screenshot::BitmapMaker.hwnd(/Calculator/)
55
+ sleep 0.1
56
+ end
57
+ # just in case of slow PC
58
+ sleep 2
59
+ end
60
+
61
+ def maximize title
62
+ Win32::Screenshot::BitmapMaker.show_window(Win32::Screenshot::BitmapMaker.hwnd(title),
63
+ SW_MAXIMIZE)
64
+ sleep 1
65
+ end
66
+
67
+ def minimize title
68
+ Win32::Screenshot::BitmapMaker.show_window(Win32::Screenshot::BitmapMaker.hwnd(title),
69
+ SW_MINIMIZE)
70
+ sleep 1
71
+ end
72
+
73
+ def resize title
74
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(title)
75
+ set_window_pos(hwnd,
76
+ HWND_TOPMOST,
77
+ 0, 0, 150, 238,
78
+ SWP_NOMOVE)
79
+ set_window_pos(hwnd,
80
+ HWND_NOTOPMOST,
81
+ 0, 0, 0, 0,
82
+ SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE)
83
+ sleep 1
84
+ end
85
+ end