sensible-cinema 0.28.1 → 0.34.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. data/{README → README.TXT} +35 -14
  2. data/Rakefile +49 -41
  3. data/TODO +337 -250
  4. data/VERSION +1 -1
  5. data/bin/sensible-cinema +15 -14
  6. data/bin/sensible-cinema-cli +1 -1
  7. data/business_ideas.txt +8 -0
  8. data/change_log_with_feature_list.txt +198 -1
  9. data/documentation/is_it_legal_to_copy_dvds.txt +44 -30
  10. data/goc.bat +1 -1
  11. data/gpl-2.0.txt +339 -0
  12. data/history_and_related_works_list.txt +37 -33
  13. data/{cone.png → inventionzy_files/cone.png} +0 -0
  14. data/legal_draft +23 -0
  15. data/lib/add_any_bundled_gems_to_load_path.rb +4 -3
  16. data/lib/check_installed_mac.rb +10 -10
  17. data/lib/count_down_timer_jruby_swing.rb +4 -4
  18. data/lib/edl_parser.rb +155 -142
  19. data/lib/extract/dumpstream.bat +1 -0
  20. data/lib/extract/get_init.bat +3 -0
  21. data/lib/extract/pause_early.rb +13 -0
  22. data/lib/gui/base.rb +707 -0
  23. data/lib/gui/create-file.rb +244 -0
  24. data/lib/gui/create.rb +565 -0
  25. data/lib/gui/dependencies.rb +177 -0
  26. data/lib/gui/normal.rb +190 -0
  27. data/lib/gui/{sensible-cinema-upconvert.rb → upconvert.rb} +33 -14
  28. data/lib/keyboard_input.rb +0 -2
  29. data/lib/mencoder_wrapper.rb +8 -3
  30. data/lib/movie_hasher.rb +27 -0
  31. data/lib/mplayer_edl.rb +1 -0
  32. data/lib/subtitle_profanity_finder.rb +141 -103
  33. data/lib/vlc_programmer.rb +1 -1
  34. data/lib/zoom_player_max_edl.rb +50 -0
  35. data/{developer_how_to_contribute_to_the_project.txt → notes_for_potential_developers.txt} +18 -11
  36. data/roadmap_possibilities +12 -0
  37. data/spec/arse.srt +6 -1
  38. data/spec/dragon.srt +3 -0
  39. data/spec/edl_parser.spec.rb +57 -52
  40. data/spec/mencoder_wrapper.spec.rb +26 -19
  41. data/spec/mplayer_edl.spec.rb +40 -10
  42. data/spec/notes +3043 -9
  43. data/spec/sensible_cinema_gui.spec.rb +8 -3
  44. data/spec/subtitle_profanity_finder.spec.rb +91 -36
  45. data/spec/zoom_player_max_edl.spec.rb +29 -0
  46. data/template_bats/README_DISTRO.TXT +3 -1
  47. data/template_bats/RUN SENSIBLE CINEMA CLICK HERE WINDOWS.bat +25 -0
  48. data/template_bats/mac/RUN SENSIBLE CINEMA CLICK HERE.command +2 -1
  49. data/template_bats/mac/advanced--create or edit sensible cinema edit list files.command +2 -1
  50. data/template_bats/mac/advanced--run-upconverting-video-player.command +2 -1
  51. data/template_bats/pc/advanced--create or edit sensible cinema edit list files.bat +2 -0
  52. data/template_bats/pc/advanced--run-upconverting-video-player.bat +2 -0
  53. data/todo.inventionzy.txt +69 -2
  54. data/todo.propaganda +34 -10
  55. data/todo.upconvert +8 -1
  56. data/{upconvert_netflix/latest2 → upconvert_from_screen}/go_upscaling.bat +0 -0
  57. data/{also_see_rogerdpack_youtube_account_and_sourceforge_files_movies_account → upconvert_from_screen/go_upscaling_works} +0 -0
  58. data/{upconvert_netflix → upconvert_from_screen/old}/latest2/combine_video.avs +0 -0
  59. data/{upconvert_netflix → upconvert_from_screen/old}/latest2/go_no_upscaling.bat +0 -0
  60. data/upconvert_from_screen/old/latest2/go_upscaling.bat +12 -0
  61. data/{upconvert_netflix → upconvert_from_screen/old}/latest2/push2.GRF +0 -0
  62. data/upconvert_from_screen/old/latest2/push3.grf +0 -0
  63. data/{upconvert_netflix → upconvert_from_screen/old}/latest2/setup_capture_coords.rb +0 -0
  64. data/{upconvert_netflix → upconvert_from_screen/old}/latest2/setup_directshow_filter_params.rb +0 -0
  65. data/{upconvert_netflix → upconvert_from_screen/old}/latest2/upconvert_from_screen_me2.avs +1 -1
  66. data/{upconvert_netflix → upconvert_from_screen}/old/latest_now_possibly_oudated/push2.GRF +0 -0
  67. data/{upconvert_netflix → upconvert_from_screen}/old/latest_now_possibly_oudated/upconvert_from_screen_me2.avs +0 -0
  68. data/{upconvert_netflix → upconvert_from_screen}/old/position_window.png +0 -0
  69. data/{upconvert_netflix → upconvert_from_screen}/old/push_source_desktop.GRF +0 -0
  70. data/{upconvert_netflix → upconvert_from_screen/old}/record_screen/record.bat +0 -0
  71. data/{upconvert_netflix → upconvert_from_screen}/old/upconvert_from_screen.avs +0 -0
  72. data/{upconvert_netflix → upconvert_from_screen}/old/upconvert_from_screen_me.avs +0 -0
  73. data/{upconvert_netflix → upconvert_from_screen}/old/upconvert_from_screen_me2.avs +0 -0
  74. data/{upconvert_netflix → upconvert_from_screen}/old/upconvert_from_screen_me_push_source.avs +0 -0
  75. data/{upconvert_netflix → upconvert_from_screen}/old/uscreen.GRF +0 -0
  76. data/{upconvert_netflix → upconvert_from_screen}/old/uscreen_me.GRF +0 -0
  77. data/upconvert_from_screen/push3.grf +0 -0
  78. data/upconvert_from_screen/upconvert_from_screen_me2.avs +19 -0
  79. data/vendor/mplayer_patches/apply.bat +12 -0
  80. data/vendor/{rdp-win32screenshot-0.0.9/RDP_BRANCH_HAS_MASTER_WITH_CORRECT_VERSION_NUMBER → mplayer_patches/configure_from_betterlogic} +0 -0
  81. data/vendor/mplayer_patches/libdvdnav/2905259c3b45529b3d8dedba572b6e4f67a2d8f4.diff +19 -0
  82. data/vendor/mplayer_patches/libdvdnav/83f1c9256f500285e46f1e44bcc74ffce90159db.diff +16 -0
  83. data/vendor/mplayer_patches/libdvdnav/eb91fb74680d30322461a1b9e425918ad4e2b2df.diff +21 -0
  84. data/vendor/mplayer_patches/libdvdnav/jump_to_time.diff +654 -0
  85. data/vendor/mplayer_patches/libdvdnav/non_strict.diff +13 -0
  86. data/vendor/mplayer_patches/mplayer_edl.diff +354 -0
  87. data/vendor/mplayer_patches/port_dir/PortIndex.quick +2 -0
  88. data/vendor/mplayer_patches/port_dir/how_to +13 -0
  89. data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/Portfile +300 -0
  90. data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/files/configure.x11.patch +20 -0
  91. data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/files/llvm-gcc-workaround.patch +11 -0
  92. data/vendor/mplayer_patches/port_dir/multimedia/rdp-projects/Portfile +43 -0
  93. data/vendor/{rdp-win32screenshot-0.0.9/RDP_VERSION_IS_IN_RDP_BRANCH → mplayer_patches/updated_lib_too} +0 -0
  94. data/vendor/{readme.txt → readme.txt.setpriority} +0 -0
  95. data/www/content_editor.html +28 -28
  96. data/www/index.html +6 -1
  97. data/www/upconverting_movie_player.html +13 -3
  98. data/www/youtube_edl/.htaccess +44 -0
  99. data/{inventionzy_files/control_youtube.html → www/youtube_edl/control_youtube.rhtml} +39 -33
  100. data/www/youtube_edl/dispatch.fcgi +25 -0
  101. data/www/youtube_edl/render_edited.rb +25 -0
  102. data/{inventionzy_files/serve.rb → www/youtube_edl/server_this_dir.rb} +0 -0
  103. data/www/youtube_edl/todo +23 -0
  104. data/www/zoomplayer_max.png +0 -0
  105. data/zamples/edit_decision_lists/dvds/Harry Potter 2 chamber of secrets.txt +10 -5
  106. data/zamples/edit_decision_lists/dvds/aladdin.txt +30 -0
  107. data/zamples/edit_decision_lists/dvds/bambi.txt +1 -1
  108. data/zamples/edit_decision_lists/dvds/big_buck_bunny_dvd.txt +2 -0
  109. data/zamples/edit_decision_lists/dvds/bobs_big_plan.txt +2 -2
  110. data/zamples/edit_decision_lists/dvds/cars_2.txt +26 -0
  111. data/zamples/edit_decision_lists/dvds/cars_disney.txt +1 -1
  112. data/zamples/edit_decision_lists/dvds/condor_man_widescreen.txt +22 -0
  113. data/zamples/edit_decision_lists/dvds/court_jester.txt +10 -13
  114. data/zamples/edit_decision_lists/dvds/edls_being_edited/making_marriage_work.txt +15 -0
  115. data/zamples/edit_decision_lists/dvds/edls_being_edited/national_treasure.txt +23 -0
  116. data/zamples/edit_decision_lists/dvds/edls_being_edited/ratatouille.txt +35 -0
  117. data/zamples/edit_decision_lists/dvds/edls_being_edited/the_explorers.txt +49 -0
  118. data/zamples/edit_decision_lists/dvds/finding_neverland.txt +32 -0
  119. data/zamples/edit_decision_lists/dvds/flight_of_the_navigator.txt +22 -16
  120. data/zamples/edit_decision_lists/dvds/harry_potter_3_prisoner_of_azkaban.txt +21 -4
  121. data/zamples/edit_decision_lists/dvds/hitchhiker's_guide_to_the_galaxy.txt +1 -1
  122. data/zamples/edit_decision_lists/dvds/{edls_being_edited/king_of_kings.txt → king_of_kings.txt} +5 -5
  123. data/zamples/edit_decision_lists/dvds/nanny_mcphee.txt +31 -0
  124. data/zamples/edit_decision_lists/dvds/pack_jackson_wedding_2007-03-03.txt +9 -2
  125. data/zamples/edit_decision_lists/dvds/remember_the_titans.txt +35 -0
  126. data/zamples/edit_decision_lists/dvds/sintel_open_source_blender_ntsc_dvd.txt +8 -4
  127. data/zamples/edit_decision_lists/dvds/speed_racer.txt +1 -1
  128. data/zamples/edit_decision_lists/dvds/tangled.txt +21 -0
  129. data/zamples/edit_decision_lists/dvds/tron_legacy.txt +4 -1
  130. data/zamples/edit_decision_lists/files/conference_music_video.txt +10 -0
  131. data/zamples/edit_decision_lists/notes_on_movies_without_edls_yet/tron.txt +10 -0
  132. data/zamples/edit_decision_lists/old_not_yet_updated/example_edit_decision_list.txt +1 -1
  133. metadata +139 -117
  134. data/conclusions +0 -6
  135. data/documentation/how_to_create_your_own_delete_lists.txt +0 -69
  136. data/lib/gui/sensible-cinema-base.rb +0 -620
  137. data/lib/gui/sensible-cinema-create.rb +0 -331
  138. data/lib/gui/sensible-cinema-dependencies.rb +0 -28
  139. data/lib/gui/sensible-cinema-normal.rb +0 -351
  140. data/lib/gui/sensible-cinema-side-by-side.rb +0 -27
  141. data/lib/shutdown_kill.rb +0 -32
  142. data/lib/storage.rb +0 -105
  143. data/ocr.todo_if_need_speed +0 -6
  144. data/upconvert_netflix/record_screen/recording/1.png +0 -0
  145. data/upconvert_netflix/record_screen/recording/10.png +0 -0
  146. data/upconvert_netflix/record_screen/recording/2.png +0 -0
  147. data/upconvert_netflix/record_screen/recording/3.png +0 -0
  148. data/upconvert_netflix/record_screen/recording/4.png +0 -0
  149. data/upconvert_netflix/record_screen/recording/5.png +0 -0
  150. data/upconvert_netflix/record_screen/recording/6.png +0 -0
  151. data/upconvert_netflix/record_screen/recording/7.png +0 -0
  152. data/upconvert_netflix/record_screen/recording/8.png +0 -0
  153. data/upconvert_netflix/record_screen/recording/9.png +0 -0
  154. data/upconvert_netflix/record_screen/recording/d.png +0 -0
  155. data/vendor/monkey.png +0 -0
  156. data/vendor/rdp-win32screenshot-0.0.9/.document +0 -5
  157. data/vendor/rdp-win32screenshot-0.0.9/History.rdoc +0 -53
  158. data/vendor/rdp-win32screenshot-0.0.9/LICENSE +0 -20
  159. data/vendor/rdp-win32screenshot-0.0.9/README.rdoc +0 -95
  160. data/vendor/rdp-win32screenshot-0.0.9/Rakefile +0 -63
  161. data/vendor/rdp-win32screenshot-0.0.9/VERSION +0 -1
  162. data/vendor/rdp-win32screenshot-0.0.9/enumerated +0 -55576
  163. data/vendor/rdp-win32screenshot-0.0.9/lib/aero_offscreen_srccopy_captureblt_doesnt_have_everything.bmp.gz +0 -0
  164. data/vendor/rdp-win32screenshot-0.0.9/lib/enumerate.rb +0 -6
  165. data/vendor/rdp-win32screenshot-0.0.9/lib/firefox.bmp +0 -0
  166. data/vendor/rdp-win32screenshot-0.0.9/lib/normal.bmp +0 -0
  167. data/vendor/rdp-win32screenshot-0.0.9/lib/normal2.bmp +0 -0
  168. data/vendor/rdp-win32screenshot-0.0.9/lib/notes +0 -5
  169. data/vendor/rdp-win32screenshot-0.0.9/lib/snapshot.rb +0 -10
  170. data/vendor/rdp-win32screenshot-0.0.9/lib/srccopy.bmp +0 -0
  171. data/vendor/rdp-win32screenshot-0.0.9/lib/srccopyplus.bmp +0 -0
  172. data/vendor/rdp-win32screenshot-0.0.9/lib/srccopyplusdirectx.bmp +0 -0
  173. data/vendor/rdp-win32screenshot-0.0.9/lib/vc.bmp +0 -0
  174. data/vendor/rdp-win32screenshot-0.0.9/lib/win32/screenshot.rb +0 -95
  175. data/vendor/rdp-win32screenshot-0.0.9/lib/win32/screenshot/bitmap_maker.rb +0 -200
  176. data/vendor/rdp-win32screenshot-0.0.9/lib/win32/util.rb +0 -93
  177. data/vendor/rdp-win32screenshot-0.0.9/spec/spec.opts +0 -1
  178. data/vendor/rdp-win32screenshot-0.0.9/spec/spec_helper.rb +0 -85
  179. data/vendor/rdp-win32screenshot-0.0.9/spec/win32_screenshot_spec.rb +0 -194
  180. data/vendor/rdp-win32screenshot-0.0.9/spec/win32_screenshot_util_spec.rb +0 -75
  181. data/vendor/rdp-win32screenshot-0.0.9/win32screenshot.gemspec +0 -69
  182. data/vendor/tsmuxer_1.10.6/licence.txt +0 -42
  183. data/zamples/edit_decision_lists/dvds/making_marriage_work.txt +0 -15
  184. data/zamples/edit_decision_lists/notes/tron.txt +0 -4
  185. data/zamples/edit_decision_lists/old_not_yet_updated/dvds/making marriage work.txt +0 -9
@@ -1,6 +0,0 @@
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
@@ -1,5 +0,0 @@
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.
@@ -1,10 +0,0 @@
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
@@ -1,95 +0,0 @@
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
@@ -1,200 +0,0 @@
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
@@ -1,93 +0,0 @@
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
@@ -1,85 +0,0 @@
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