content-editing-movie-player 0.38.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (273) hide show
  1. data/.gitmodules +3 -0
  2. data/.rvmrc +1 -0
  3. data/LICENSE.TXT +20 -0
  4. data/README.TXT +225 -0
  5. data/Rakefile +206 -0
  6. data/TODO +740 -0
  7. data/VERSION +1 -0
  8. data/_DO_NOT_RUN_IT_FROM_HERE_DOWNLOAD_THE_RELEASE_ZIP_FROM_SOURCEFORGE_INSTEAD +0 -0
  9. data/bin/sensible-cinema +60 -0
  10. data/bin/sensible-cinema-cli +161 -0
  11. data/business_ideas.txt +21 -0
  12. data/change_log_with_feature_list.txt +952 -0
  13. data/documentation/DOCUMENTATION_README.TXT +44 -0
  14. data/documentation/how_to_get_files_from_dvd.txt +30 -0
  15. data/documentation/is_it_legal_to_copy_dvds.txt +97 -0
  16. data/documentation/troubleshooting.txt +30 -0
  17. data/documentation/upconversion.txt +4 -0
  18. data/experimental_online_player_ocr_readme.txt +45 -0
  19. data/go +1 -0
  20. data/go.bat +2 -0
  21. data/go.sh +1 -0
  22. data/go_ocr_tracker.bat +1 -0
  23. data/goc +1 -0
  24. data/goc.bat +1 -0
  25. data/goc.sh +1 -0
  26. data/gpl-2.0.txt +339 -0
  27. data/gplv3.txt +219 -0
  28. data/history_and_related_works_list.txt +108 -0
  29. data/inventionzy_files/cone.png +0 -0
  30. data/inventionzy_files/md5s.txt +53 -0
  31. data/inventionzy_files/play_with_inserted_scene.bat +8 -0
  32. data/inventionzy_files/play_with_overlay.bat +24 -0
  33. data/inventionzy_files/transcript_mute_vlc.txt +117 -0
  34. data/legal_draft +23 -0
  35. data/lib/add_any_bundled_gems_to_load_path.rb +32 -0
  36. data/lib/auto_window_finder.rb +41 -0
  37. data/lib/blanker.rb +104 -0
  38. data/lib/check_installed_mac.rb +34 -0
  39. data/lib/convert_thirty_fps.rb +20 -0
  40. data/lib/edl_parser.rb +387 -0
  41. data/lib/eight_three.rb +28 -0
  42. data/lib/extract/dumpstream.bat +1 -0
  43. data/lib/extract/get_init.bat +3 -0
  44. data/lib/extract/pause_early.rb +13 -0
  45. data/lib/fake_blanker.rb +35 -0
  46. data/lib/frame_accurate.rb +3 -0
  47. data/lib/gui/base.rb +748 -0
  48. data/lib/gui/create-file.rb +24 -0
  49. data/lib/gui/create.rb +581 -0
  50. data/lib/gui/dependencies.rb +219 -0
  51. data/lib/gui/normal.rb +123 -0
  52. data/lib/gui/upconvert.rb +284 -0
  53. data/lib/keyboard_input.rb +60 -0
  54. data/lib/media_info_parser.rb +27 -0
  55. data/lib/mouse_forever.rb +19 -0
  56. data/lib/movie_hasher.rb +27 -0
  57. data/lib/mplayer_edl.rb +42 -0
  58. data/lib/muter.rb +87 -0
  59. data/lib/ocr.rb +125 -0
  60. data/lib/ocr_seed/netflix_b9.bmp +0 -0
  61. data/lib/overlayer.rb +373 -0
  62. data/lib/screen_tracker.rb +269 -0
  63. data/lib/subtitle_profanity_finder.rb +294 -0
  64. data/lib/vlc_programmer.rb +112 -0
  65. data/lib/zoom_player_max_edl.rb +50 -0
  66. data/never_do +40 -0
  67. data/notes_for_potential_developers.txt +46 -0
  68. data/preamble +17 -0
  69. data/roadmap_possibilities +12 -0
  70. data/spec/arse.srt +41 -0
  71. data/spec/auto_window_finder.spec.rb +65 -0
  72. data/spec/bad_beginning.srt +3778 -0
  73. data/spec/blanker.spec.rb +60 -0
  74. data/spec/common.rb +81 -0
  75. data/spec/convert_image.rb +25 -0
  76. data/spec/deity_end.srt +11 -0
  77. data/spec/dragon.srt +34 -0
  78. data/spec/edl_parser.spec.rb +270 -0
  79. data/spec/frame_accurate.spec.rb +71 -0
  80. data/spec/keyboard_input.spec.rb +73 -0
  81. data/spec/media_info_parser.spec.rb +29 -0
  82. data/spec/mplayer_edl.spec.rb +100 -0
  83. data/spec/muter.spec.rb +50 -0
  84. data/spec/notes +4996 -0
  85. data/spec/ocr.spec.rb +119 -0
  86. data/spec/overlayer.spec.rb +440 -0
  87. data/spec/screen_tracker.spec.rb +318 -0
  88. data/spec/sensible_cinema_gui.spec.rb +452 -0
  89. data/spec/subtitle_profanity_finder.spec.rb +224 -0
  90. data/spec/test_yaml.yml +4 -0
  91. data/spec/tsmuxer.output +33 -0
  92. data/spec/vlc_programmer.spec.rb +124 -0
  93. data/spec/youtube_edl.spec.rb +28 -0
  94. data/spec/zoom_player_max_edl.spec.rb +29 -0
  95. data/template_bats/README_DISTRO.TXT +8 -0
  96. data/template_bats/RUN SENSIBLE CINEMA CLICK HERE WINDOWS.bat +25 -0
  97. data/template_bats/_DO_NOT_RUN_IT_FROM_HERE_DOWNLOAD_THE_RELEASE_ZIP_FROM_SOURCEFORGE_INSTEAD +0 -0
  98. data/template_bats/mac/RUN SENSIBLE CINEMA CLICK HERE.command +5 -0
  99. data/template_bats/mac/advanced--create or edit sensible cinema edit list files.command +3 -0
  100. data/template_bats/mac/advanced--run-upconverting-video-player.command +3 -0
  101. data/template_bats/pc/advanced--create or edit sensible cinema edit list files.bat +2 -0
  102. data/template_bats/pc/advanced--run-upconverting-video-player.bat +2 -0
  103. data/todo.build_library.txt +11 -0
  104. data/todo.inventionzy.txt +162 -0
  105. data/todo.open_edl_list_org.txt +169 -0
  106. data/todo.propaganda +107 -0
  107. data/todo.subtitle +17 -0
  108. data/todo.upconvert +53 -0
  109. data/upconvert.bat +1 -0
  110. data/upconvert_from_screen/go_upscaling.bat +12 -0
  111. data/upconvert_from_screen/go_upscaling_works +0 -0
  112. data/upconvert_from_screen/old/latest2/combine_video.avs +23 -0
  113. data/upconvert_from_screen/old/latest2/go_no_upscaling.bat +1 -0
  114. data/upconvert_from_screen/old/latest2/go_upscaling.bat +12 -0
  115. data/upconvert_from_screen/old/latest2/push2.GRF +0 -0
  116. data/upconvert_from_screen/old/latest2/push3.grf +0 -0
  117. data/upconvert_from_screen/old/latest2/setup_capture_coords.rb +27 -0
  118. data/upconvert_from_screen/old/latest2/setup_directshow_filter_params.rb +29 -0
  119. data/upconvert_from_screen/old/latest2/upconvert_from_screen_me2.avs +19 -0
  120. data/upconvert_from_screen/old/latest_now_possibly_oudated/push2.GRF +0 -0
  121. data/upconvert_from_screen/old/latest_now_possibly_oudated/upconvert_from_screen_me2.avs +18 -0
  122. data/upconvert_from_screen/old/position_window.png +0 -0
  123. data/upconvert_from_screen/old/push_source_desktop.GRF +0 -0
  124. data/upconvert_from_screen/old/record_screen/record.bat +2 -0
  125. data/upconvert_from_screen/old/upconvert_from_screen.avs +21 -0
  126. data/upconvert_from_screen/old/upconvert_from_screen_me.avs +21 -0
  127. data/upconvert_from_screen/old/upconvert_from_screen_me2.avs +3 -0
  128. data/upconvert_from_screen/old/upconvert_from_screen_me_push_source.avs +3 -0
  129. data/upconvert_from_screen/old/uscreen.GRF +0 -0
  130. data/upconvert_from_screen/old/uscreen_me.GRF +0 -0
  131. data/upconvert_from_screen/push3.grf +0 -0
  132. data/upconvert_from_screen/upconvert_from_screen_me2.avs +19 -0
  133. data/vendor/movie-content-editor-read-only/.metadata/.lock +0 -0
  134. data/vendor/movie-content-editor-read-only/.metadata/.mylyn/.tasks.xml.zip +0 -0
  135. data/vendor/movie-content-editor-read-only/.metadata/.mylyn/repositories.xml.zip +0 -0
  136. data/vendor/movie-content-editor-read-only/.metadata/.mylyn/tasks.xml.zip +0 -0
  137. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version +1 -0
  138. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index +0 -0
  139. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version +1 -0
  140. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/2.tree +0 -0
  141. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources +0 -0
  142. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs +3 -0
  143. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs +14 -0
  144. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs +3 -0
  145. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs +5 -0
  146. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs +3 -0
  147. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache +0 -0
  148. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat +0 -0
  149. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml +2 -0
  150. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml +2 -0
  151. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml +10 -0
  152. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml +11 -0
  153. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml +4 -0
  154. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml +10 -0
  155. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml +232 -0
  156. data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml +4 -0
  157. data/vendor/movie-content-editor-read-only/.metadata/version.ini +1 -0
  158. data/vendor/movie-content-editor-read-only/.project +17 -0
  159. data/vendor/movie-content-editor-read-only/.pydevproject +11 -0
  160. data/vendor/movie-content-editor-read-only/.settings/org.eclipse.core.resources.prefs +6 -0
  161. data/vendor/movie-content-editor-read-only/SubIt.py +171 -0
  162. data/vendor/movie-content-editor-read-only/VLCMacVideo.py +257 -0
  163. data/vendor/movie-content-editor-read-only/VideoMac.ui +102 -0
  164. data/vendor/movie-content-editor-read-only/badwords.txt +4 -0
  165. data/vendor/movie-content-editor-read-only/blank.srt +4 -0
  166. data/vendor/movie-content-editor-read-only/edit.py +197 -0
  167. data/vendor/movie-content-editor-read-only/mergeCommands.py +73 -0
  168. data/vendor/movie-content-editor-read-only/mute.txt +5 -0
  169. data/vendor/movie-content-editor-read-only/panda.srt +4235 -0
  170. data/vendor/movie-content-editor-read-only/panda_custom.txt +3 -0
  171. data/vendor/movie-content-editor-read-only/panda_edit.srt +4235 -0
  172. data/vendor/movie-content-editor-read-only/subtitle.py +90 -0
  173. data/vendor/movie-content-editor-read-only/vlc.py +5579 -0
  174. data/vendor/movie-content-editor-read-only/vlcwidget.py +154 -0
  175. data/vendor/mplayer_patches/how_to_doze.bat +6 -0
  176. data/vendor/mplayer_patches/port_dir/PortIndex.quick +2 -0
  177. data/vendor/mplayer_patches/port_dir/how_to +20 -0
  178. data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/Portfile +285 -0
  179. data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/files/configure.x11.patch +20 -0
  180. data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/files/llvm-gcc-workaround.patch +11 -0
  181. data/vendor/mplayer_patches/port_dir/multimedia/rdp-projects/Portfile +43 -0
  182. data/vendor/mplayer_patches/port_dir_is_for_mac +0 -0
  183. data/www/content_editor.html +92 -0
  184. data/www/index.html +47 -0
  185. data/www/upconverting_movie_player.html +62 -0
  186. data/www/video reel.jpg +0 -0
  187. data/www/youtube_edl/.htaccess +44 -0
  188. data/www/youtube_edl/control_youtube.rhtml +141 -0
  189. data/www/youtube_edl/dispatch.fcgi +25 -0
  190. data/www/youtube_edl/render_edited.rb +25 -0
  191. data/www/youtube_edl/server_this_dir.rb +6 -0
  192. data/www/youtube_edl/todo +23 -0
  193. data/www/zoomplayer_max.png +0 -0
  194. data/zamples/edit_decision_lists/dvds/Harry Potter 2 chamber of secrets.txt +22 -0
  195. data/zamples/edit_decision_lists/dvds/aa_example_delete_list_that_has_no_cuts_in_it.txt +10 -0
  196. data/zamples/edit_decision_lists/dvds/aladdin.txt +30 -0
  197. data/zamples/edit_decision_lists/dvds/bambi.txt +17 -0
  198. data/zamples/edit_decision_lists/dvds/big_buck_bunny_dvd.txt +23 -0
  199. data/zamples/edit_decision_lists/dvds/bob the builder pets in a pickle.txt +10 -0
  200. data/zamples/edit_decision_lists/dvds/bobs_big_plan.txt +10 -0
  201. data/zamples/edit_decision_lists/dvds/cars_2.txt +26 -0
  202. data/zamples/edit_decision_lists/dvds/cars_disney.txt +40 -0
  203. data/zamples/edit_decision_lists/dvds/condor_man_widescreen.txt +22 -0
  204. data/zamples/edit_decision_lists/dvds/cool runnings.txt +53 -0
  205. data/zamples/edit_decision_lists/dvds/court_jester.txt +24 -0
  206. data/zamples/edit_decision_lists/dvds/edls_being_edited/amazing_grace.txt +49 -0
  207. data/zamples/edit_decision_lists/dvds/edls_being_edited/father_goose.txt +41 -0
  208. data/zamples/edit_decision_lists/dvds/edls_being_edited/harry_potter_and_the_goblet_of_fire.txt +45 -0
  209. data/zamples/edit_decision_lists/dvds/edls_being_edited/hugo.txt +31 -0
  210. data/zamples/edit_decision_lists/dvds/edls_being_edited/making_marriage_work.txt +15 -0
  211. data/zamples/edit_decision_lists/dvds/edls_being_edited/national_treasure.txt +26 -0
  212. data/zamples/edit_decision_lists/dvds/edls_being_edited/percy_jackson_lightening_thief.txt +40 -0
  213. data/zamples/edit_decision_lists/dvds/edls_being_edited/percy_jackson_lightening_thief_mute_scary.txt +23 -0
  214. data/zamples/edit_decision_lists/dvds/edls_being_edited/prince_of_egypt.txt +28 -0
  215. data/zamples/edit_decision_lists/dvds/edls_being_edited/puss_in_boots.txt +33 -0
  216. data/zamples/edit_decision_lists/dvds/edls_being_edited/ratatouille.txt +35 -0
  217. data/zamples/edit_decision_lists/dvds/edls_being_edited/rio.txt +24 -0
  218. data/zamples/edit_decision_lists/dvds/edls_being_edited/test_delete_list_for_experimenting_with.txt +10 -0
  219. data/zamples/edit_decision_lists/dvds/edls_being_edited/the_explorers.txt +49 -0
  220. data/zamples/edit_decision_lists/dvds/finding_neverland.txt +32 -0
  221. data/zamples/edit_decision_lists/dvds/flight_of_the_navigator.txt +40 -0
  222. data/zamples/edit_decision_lists/dvds/happiest baby on the block.txt +9 -0
  223. data/zamples/edit_decision_lists/dvds/harry_potter_3_prisoner_of_azkaban.txt +37 -0
  224. data/zamples/edit_decision_lists/dvds/hitchhiker's_guide_to_the_galaxy.txt +32 -0
  225. data/zamples/edit_decision_lists/dvds/how_to_train_your_dragon.txt +25 -0
  226. data/zamples/edit_decision_lists/dvds/if_a_man_answers.txt +43 -0
  227. data/zamples/edit_decision_lists/dvds/innerspace.txt +77 -0
  228. data/zamples/edit_decision_lists/dvds/iq.txt +32 -0
  229. data/zamples/edit_decision_lists/dvds/king_of_kings.txt +28 -0
  230. data/zamples/edit_decision_lists/dvds/kung_fu_panda_1.txt +17 -0
  231. data/zamples/edit_decision_lists/dvds/legend_of_the_guardians_the_owls_of_gahoole.txt +18 -0
  232. data/zamples/edit_decision_lists/dvds/monsters_vs_aliens.txt +41 -0
  233. data/zamples/edit_decision_lists/dvds/muppet_treasure_island.txt +21 -0
  234. data/zamples/edit_decision_lists/dvds/nanny_mcphee.txt +31 -0
  235. data/zamples/edit_decision_lists/dvds/narnia_voyage_of_the_dawn_treader.txt +16 -0
  236. data/zamples/edit_decision_lists/dvds/pack_jackson_wedding_2007-03-03.txt +31 -0
  237. data/zamples/edit_decision_lists/dvds/peter_pan.txt +29 -0
  238. data/zamples/edit_decision_lists/dvds/remember_the_titans.txt +35 -0
  239. data/zamples/edit_decision_lists/dvds/sintel_open_source_blender_ntsc_dvd.txt +22 -0
  240. data/zamples/edit_decision_lists/dvds/snow_white_and_the_7_dwarfs_1937.txt +19 -0
  241. data/zamples/edit_decision_lists/dvds/speed_racer.txt +47 -0
  242. data/zamples/edit_decision_lists/dvds/tangled.txt +21 -0
  243. data/zamples/edit_decision_lists/dvds/tron_legacy.txt +29 -0
  244. data/zamples/edit_decision_lists/dvds/turn_around_alma_younger.txt +17 -0
  245. data/zamples/edit_decision_lists/files/conference_music_video.txt +10 -0
  246. data/zamples/edit_decision_lists/netflix_instant/avatar-last-air-bender-movie.txt +13 -0
  247. data/zamples/edit_decision_lists/netflix_instant/avatar-last-airbender-series.txt +1 -0
  248. data/zamples/edit_decision_lists/netflix_instant/greatest_story_ever_told_netflix.txt +10 -0
  249. data/zamples/edit_decision_lists/netflix_instant/wrinkle-in-time.txt +23 -0
  250. data/zamples/edit_decision_lists/notes_on_movies_without_edls_yet/tron.txt +10 -0
  251. data/zamples/edit_decision_lists/old_not_yet_updated/dvds/White Christmas.txt +15 -0
  252. data/zamples/edit_decision_lists/old_not_yet_updated/dvds/all_dogs_go_to_heaven.txt +9 -0
  253. data/zamples/edit_decision_lists/old_not_yet_updated/dvds/cars_disney.txt +24 -0
  254. data/zamples/edit_decision_lists/old_not_yet_updated/dvds/happy_feet.txt +12 -0
  255. data/zamples/edit_decision_lists/old_not_yet_updated/dvds/labyrinth.txt +17 -0
  256. data/zamples/edit_decision_lists/old_not_yet_updated/dvds/star_trek_generations_hulu.txt +8 -0
  257. data/zamples/edit_decision_lists/old_not_yet_updated/example_edit_decision_list.txt +14 -0
  258. data/zamples/edit_decision_lists/old_not_yet_updated/youtube/gummy_bear_song_youtube.txt +9 -0
  259. data/zamples/edit_decision_lists/youtube/demo_mutes.txt +12 -0
  260. data/zamples/edit_decision_lists/youtube/nuki_song_youtube.txt +14 -0
  261. data/zamples/edit_decision_lists/youtube/nuki_song_youtube_pointer.txt +3 -0
  262. data/zamples/players/how_to_create_more_players.txt +24 -0
  263. data/zamples/players/hulu/total_length_over_an_hour.txt +25 -0
  264. data/zamples/players/netflix/netflix_firefox_non_maximized.txt +25 -0
  265. data/zamples/players/vlc/full_screened_total_length_over_an_hour.txt +27 -0
  266. data/zamples/players/vlc/windowed_total_length_over_an_hour.txt +26 -0
  267. data/zamples/players/vlc/windowed_total_length_under_an_hour.txt +22 -0
  268. data/zamples/players/youtube/full_screened_1024x768.txt +20 -0
  269. data/zamples/players/youtube/full_screened_1152x864.txt +20 -0
  270. data/zamples/players/youtube/full_screened_1680x1050.txt +20 -0
  271. data/zamples/players/youtube/normal_in_youtube.com.chrome.txt +23 -0
  272. data/zamples/players/youtube/note_these_assume_less_than_10_minutes_length.txt +2 -0
  273. metadata +483 -0
@@ -0,0 +1,269 @@
1
+ =begin
2
+ Copyright 2010, Roger Pack
3
+ This file is part of Sensible Cinema.
4
+
5
+ Sensible Cinema is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ Sensible Cinema is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
17
+ =end
18
+ require 'win32/screenshot'
19
+ require 'sane'
20
+ require 'yaml'
21
+ require File.dirname(__FILE__)+ '/ocr'
22
+ require 'ffi'
23
+
24
+ class ScreenTracker
25
+
26
+ extend FFI::Library
27
+ ffi_lib 'user32'
28
+ # second parameter, pointer, LPRECT is FFI::MemoryPointer.new(:long, 4)
29
+ # read it like rect.read_array_of_long(4)
30
+ attach_function :GetWindowRect, [:long, :pointer], :int # returns a BOOL
31
+
32
+ def self.new_from_yaml yaml, callback # callback can be nil, is used for timestamp changed stuff
33
+ settings = YAML.load yaml
34
+ return new(settings["name"], settings["x"], settings["y"], settings["width"],
35
+ settings["height"], settings["use_class_name"], settings["digits"], callback)
36
+ end
37
+
38
+ attr_accessor :hwnd
39
+
40
+ # digits are like {:hours => [100,5], :minute_tens, :minute_ones, :second_tens, :second_ones}
41
+ # digits share the height start point, have their own x and width...
42
+ def initialize name_or_regex, x, y, width, height, use_class_name=nil, digits=nil, callback=nil
43
+ # cache to save us 0.00445136 per time LOL
44
+ @name_or_regex = name_or_regex
45
+ @use_class_name = use_class_name
46
+ pps 'height', height, 'width', width if $VERBOSE
47
+ raise 'poor dimentia' if width <= 0 || height <= 0
48
+ get_hwnd_loop_forever
49
+ max_x, max_y = Win32::Screenshot::Util.dimensions_for(@hwnd)
50
+ if(x < 0 || y < 0)
51
+ if x < 0
52
+ x = max_x + x
53
+ end
54
+ if y < 0
55
+ y = max_y + y
56
+ end
57
+ end
58
+ @x = x; @y = y; @x2 = x+width; @y2 = y+height; @callback = callback
59
+ @max_x = max_x
60
+ raise "poor width or wrong window #{@x2} #{max_x} #{x}" if @x2 > max_x || @x2 == x
61
+ if @y2 > max_y || @y2 == y || @y2 <= 0
62
+ raise "poor height or wrong window selected #{@y2} > #{max_y} || #{@y2} == #{y} || #{@y2} <= 0"
63
+ end
64
+ if max_x == 0 || max_y == 0
65
+ # I don't think we can ever get here, because of the checks above
66
+ raise 'window invisible?'
67
+ end
68
+ @digits = digits
69
+ @previously_displayed_warning = false
70
+ @dump_digit_count = 1
71
+ pps 'using x',@x, 'from x', x, 'y', @y, 'from y', y,'x2',@x2,'y2',@y2,'digits', @digits.inspect if $VERBOSE
72
+ end
73
+
74
+ def get_hwnd_loop_forever
75
+ if @name_or_regex.to_s.downcase == 'desktop'
76
+ # full screen option
77
+ assert !@use_class_name # not an option
78
+ @hwnd = hwnd = Win32::Screenshot::BitmapMaker.desktop_window
79
+ return
80
+ else
81
+ raise if OS.mac?
82
+ @hwnd = Win32::Screenshot::BitmapMaker.hwnd(@name_or_regex, @use_class_name)
83
+ end
84
+
85
+ # display the 'found it message' only if it was previously lost...
86
+ unless @hwnd
87
+ until @hwnd
88
+ print 'unable to find the player window currently [%s] (maybe need to start program or move mouse over it)' % @name_or_regex.inspect
89
+ sleep 1
90
+ STDOUT.flush
91
+
92
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(@name_or_regex, @use_class_name)
93
+ width, height = Win32::Screenshot::Util.dimensions_for(hwnd)
94
+ p width, height
95
+ @hwnd = hwnd
96
+ end
97
+ puts 're-established contact with window'
98
+ end
99
+ true
100
+ end
101
+
102
+ # gets the snapshot of "all the digits together"
103
+ def get_bmp
104
+ # Note: we no longer bring the window to the front tho...which it needs to be in both XP and Vista to work...sigh.
105
+ Win32::Screenshot::BitmapMaker.capture_area(@hwnd,@x,@y,@x2,@y2) {|h,w,bmp| return bmp}
106
+ end
107
+
108
+ # gets snapshot of the full window
109
+ def get_full_bmp
110
+ Win32::Screenshot::BitmapMaker.capture_all(@hwnd) {|h,w,bmp| return bmp}
111
+ end
112
+
113
+ # writes out all screen tracking info to various files in the current pwd
114
+ def dump_bmps filename = 'dump.bmp'
115
+ File.binwrite filename, get_bmp
116
+ File.binwrite 'all.' + filename, get_full_bmp
117
+ dump_digits(get_digits_as_bitmaps, 'dump_bmp') if @digits
118
+ end
119
+
120
+ def dump_digits digits, message
121
+ p "#{message} dumping digits to dump no: #{@dump_digit_count} #{Time.now.to_f}"
122
+ for type, bitmap in digits
123
+ File.binwrite type.to_s + '.' + @dump_digit_count.to_s + '.bmp', bitmap
124
+ end
125
+ File.binwrite @dump_digit_count.to_s + '.mrsh', Marshal.dump(digits)
126
+ @dump_digit_count += 1
127
+ end
128
+
129
+ DIGIT_TYPES = [:hours, :minute_tens, :minute_ones, :second_tens, :second_ones]
130
+
131
+ # returns like {:hours => nil, :minutes_tens => raw_bmp, ...
132
+ def get_digits_as_bitmaps
133
+ # @digits are like {:hours => [100,5], :minute_tens => [x, width], :minute_ones, :second_tens, :second_ones}
134
+ out = {}
135
+ for type in DIGIT_TYPES
136
+ assert @digits.key?(type)
137
+ if @digits[type]
138
+ x,w = @digits[type]
139
+ if(x < 0)
140
+ x = @max_x + x
141
+ end
142
+ x2 = x + w
143
+ raise 'a digit width can never be negative #{w}' if w <= 0
144
+ y2 = @y2
145
+ width = x2 - x
146
+ height = y2 - @y
147
+ # lodo calculate these only once...
148
+ out[type] = Win32::Screenshot::BitmapMaker.capture_area(@hwnd, x, @y, x2, y2) {|h,w,bmp| bmp}
149
+ end
150
+ end
151
+ out
152
+ end
153
+
154
+ def get_relative_coords_of_timestamp_window
155
+ [@x,@y,@x2,@y2]
156
+ end
157
+
158
+ def get_coords_of_window_on_display # yea
159
+ out = FFI::MemoryPointer.new(:long, 4)
160
+ ScreenTracker.GetWindowRect @hwnd, out
161
+ out.read_array_of_long(4)
162
+ end
163
+
164
+ def identify_digit bitmap
165
+ OCR.identify_digit(bitmap, @digits)
166
+ end
167
+
168
+ # we have to wait until the next change, because when we start, it might be half-way through
169
+ # the current second...
170
+ def wait_till_next_change
171
+ original = get_bmp
172
+ time_since_last_screen_change = Time.now
173
+ loop {
174
+ # save away the current time to try and be most accurate...
175
+ time_before_current_scan = Time.now
176
+ current = get_bmp
177
+ if current != original
178
+ if @digits
179
+ got = attempt_to_get_time_from_screen time_before_current_scan
180
+ if @previously_displayed_warning && got
181
+ # reassure user :)
182
+ p 'tracking it successfully again'
183
+ @previously_displayed_warning = false
184
+ end
185
+ return got
186
+ else
187
+ puts 'screen time change only detected... [unexpected]' # unit tests do this still <sigh>
188
+ return
189
+ end
190
+ else
191
+ if(Time.now - time_since_last_screen_change > 2.0)
192
+ got_implies_able_to_still_ocr = attempt_to_get_time_from_screen time_before_current_scan
193
+ if got_implies_able_to_still_ocr
194
+ return got_implies_able_to_still_ocr
195
+ else
196
+ p 'warning--unable to track screen time for some reason [perhaps screen obscured or it\'s not playing yet?] ' + @hwnd.to_s
197
+ @previously_displayed_warning = true
198
+ # also reget window hwnd, just in case that's the problem...(can be with VLC moving from title to title)
199
+ get_hwnd_loop_forever
200
+ # LODO loop through all available player descriptions to find the right one, or a changed different new one, et al
201
+ end
202
+ time_since_last_screen_change = Time.now
203
+ end
204
+ end
205
+ sleep 0.02
206
+ }
207
+ end
208
+
209
+ def attempt_to_get_time_from_screen start_time
210
+ out = {}
211
+ # force it to have two matching snapshots in a row, to avoid race conditions grabbing the digits...
212
+ # allow youtube to update (sigh) lodo just for utube
213
+ previous = nil
214
+ sleep 0.05
215
+ current = get_digits_as_bitmaps
216
+ while previous != current
217
+ previous = current
218
+ sleep 0.05
219
+ current = get_digits_as_bitmaps
220
+ # lodo it should probably poll *before* calling this, not here...maybe?
221
+ end
222
+ assert previous == current
223
+ digits = current = previous
224
+ DIGIT_TYPES.each{|type|
225
+ if digits[type]
226
+ digit = identify_digit(digits[type])
227
+ unless digit
228
+ bitmap = digits[type]
229
+ # unable to identify a digit?
230
+ if $DEBUG || $VERBOSE && (type != :hours)
231
+ @a ||= 1
232
+ @a += 1
233
+ @already_wrote ||= {}
234
+ unless @already_wrote[bitmap]
235
+ p 'unable to identify capture!' + type.to_s + @a.to_s + ' dump:' + @dump_digit_count.to_s
236
+ File.binwrite("bad_digit#{@a}#{type}.bmp", bitmap)
237
+ @already_wrote[bitmap] = true
238
+ end
239
+ end
240
+ if type == :hours
241
+ digit = 0 # this one can fail and that's ok in VLC bottom right
242
+ else
243
+ # early (failure) return
244
+ return nil
245
+ end
246
+ else
247
+ p " got digit #{type} OCR as #{digit} which was captured to dump #{@dump_digit_count - 1} #{Time.now_f}" if $DEBUG
248
+ end
249
+ out[type] = digit
250
+ else
251
+ # there isn't one specified as being on screen, so assume it is always zero (like youtube hour)...
252
+ out[type] = 0
253
+ end
254
+ }
255
+ out = "%d:%d%d:%d%d" % DIGIT_TYPES.map{ |type| out[type] }
256
+ puts '', 'got new screen time ' + out + " (+ tracking delta:" + (Time.now - start_time).to_s + ")" if $VERBOSE
257
+ return out, Time.now-start_time
258
+ end
259
+
260
+ def process_forever_in_thread
261
+ Thread.new {
262
+ loop {
263
+ out_time, delta = wait_till_next_change
264
+ @callback.timestamp_changed out_time, delta
265
+ }
266
+ }
267
+ end
268
+
269
+ end
@@ -0,0 +1,294 @@
1
+ #
2
+ # warning: somewhat scary/explicit down there!
3
+ # see also todo.subtitle file, though what's here is mostly pretty well functional/complete
4
+ #
5
+ begin
6
+ require 'sane'
7
+ rescue LoadError
8
+ require 'rubygems'
9
+ require 'sane'
10
+ end
11
+ require_relative 'edl_parser'
12
+ require 'ostruct'
13
+
14
+ module SubtitleProfanityFinder
15
+
16
+ # splits into timestamps -> timestamps\ncontent blocks
17
+ def self.split_to_entries subtitles_raw_text
18
+ all = subtitles_raw_text.gsub("\r\n", "\n").scan(/^\d+\n\d\d:\d\d:\d\d.*?^$/m) # line endings so that it parses right when linux reads a windows file <huh?>
19
+ all.map!{|glop|
20
+ lines = glop.lines.to_a
21
+ index_line = lines[0]
22
+ timing_line = lines[1].strip
23
+ text = lines.to_a[2..-1].join("") # they still have separating "\n"'s
24
+ # create english-ified version
25
+ text.gsub!(/<(.|)(\/|)i>/i, '') # kill <i> type things
26
+ text.gsub!(/[^a-zA-Z0-9\-!,.\?'\n\(\)]/, ' ') # kill weird stuff like ellipseses, also quotes would hurt so kill them too
27
+ text.gsub!(/ +/, ' ') # remove duplicate " " 's now since we may have inserted many
28
+ # extract timing info
29
+ # "00:03:00.0" , "00:04:00.0", "violence", "of some sort",
30
+ timing_line =~ /((\d\d:\d\d:\d\d),(\d\d\d) --> (\d\d:\d\d:\d\d),(\d\d\d))/
31
+ ts_begin = "#{$2}.#{$3}"
32
+ ts_end = "#{$4}.#{$5}"
33
+ out = OpenStruct.new
34
+ out.index_number = index_line.strip.to_i
35
+ out.beginning_time = EdlParser.translate_string_to_seconds ts_begin
36
+ out.ending_time = EdlParser.translate_string_to_seconds ts_end
37
+ out.text = text.strip # harmless right?
38
+ add_single_line_minimized_text_from_multiline out
39
+ out
40
+ }
41
+ if all.size < 10
42
+ raise "unable to parse subtitle file?"
43
+ end
44
+
45
+ # strip out auto inserted trailers/headers
46
+ reg = / by|download| eng|www|http|sub/i
47
+ while all[0].text =~ reg
48
+ all.shift
49
+ end
50
+ while all[-1] =~ reg
51
+ all.pop
52
+ end
53
+ all
54
+ end
55
+
56
+ def self.add_single_line_minimized_text_from_multiline entry
57
+ entry.single_line_text = entry.text.strip.gsub(/^[- ,_\.]+/, '').gsub(/[- ,_]+$/, '').gsub(/[\r\n]/, ' ')
58
+ end
59
+
60
+ # convert string to regexp, also accomodating for "full word" type profanities
61
+ def self.convert_to_regexps profanity_hash
62
+ all_profanity_combinations = []
63
+ profanity_hash.to_a.sort.reverse.each{|profanity, sanitized|
64
+ as_regexp = Regexp.new(profanity, Regexp::IGNORECASE)
65
+ if sanitized.is_a? Array
66
+ # like 'bad word' => ['vain use', :partial_word, 'deity']
67
+ raise unless sanitized.length.in? [2, 3]
68
+ raise unless sanitized[1].in? [:full_word, :partial_word]
69
+ is_single_word_profanity = true if sanitized[1] == :full_word
70
+ if sanitized.length == 3
71
+ category = sanitized[2]
72
+ end
73
+ sanitized = sanitized[0]
74
+ end
75
+
76
+ permutations = [profanity]
77
+ if profanity =~ /l/
78
+ permutations << profanity.gsub(/l/i, 'i')
79
+ end
80
+ if profanity =~ /i/
81
+ permutations << profanity.gsub(/i/i, 'l')
82
+ end
83
+
84
+ replace_with = '[' + sanitized + ']'
85
+ category ||= sanitized
86
+
87
+ for permutation in permutations
88
+ if is_single_word_profanity
89
+ # \s is whitespace
90
+ as_regexp = Regexp.new("(?:\s|^|[^a-zA-Z])" + permutation + "(?:\s|$|[^a-zA-Z])", Regexp::IGNORECASE)
91
+ all_profanity_combinations << [as_regexp, category, ' ' + replace_with + ' '] # might introduce an extra space in there, but that's prolly ok since they're full-word already, and we collapse them
92
+ else
93
+ all_profanity_combinations << [as_regexp, category, replace_with]
94
+ end
95
+ end
96
+ }
97
+ all_profanity_combinations
98
+ end
99
+
100
+ def self.edl_output incoming_filename, extra_profanity_hash = {}, subtract_from_each_beginning_ts = 0, add_to_end_each_ts = 0, beginning_srt = 0.0, beginning_actual_movie = 0.0, ending_srt = 7200.0, ending_actual = 7200.0
101
+ edl_output_from_string(File.read(incoming_filename), extra_profanity_hash, subtract_from_each_beginning_ts, add_to_end_each_ts, beginning_srt, beginning_actual_movie, ending_srt, ending_actual)[0]
102
+ end
103
+
104
+ # **_time means "a float"
105
+
106
+ def self.edl_output_from_string subtitles, extra_profanity_hash, subtract_from_each_beginning_ts, add_to_end_each_ts, starting_time_given_srt, starting_time_actual, ending_srt_time, ending_actual_time, include_minor_profanities=true # lodo may not need include_minor_profs :P
107
+ raise if subtract_from_each_beginning_ts < 0 # these have to be positive...in my twisted paradigm
108
+ raise if add_to_end_each_ts < 0
109
+
110
+ # accomodate for both styles of rewrite, except it messes up the math...delete this soon...
111
+ # difference = starting_timestamp_given_srt - starting_timestamp_actual
112
+ # subtract_from_each_beginning_ts += difference
113
+ # add_to_end_each_ts -= difference
114
+
115
+ # you minus the initial srt time... (given)
116
+ # ratio = (end actual - init actual/ end given - init given)*(how far you are past the initial srt) plus initial actual
117
+ multiply_by_this_factor = (ending_actual_time - starting_time_actual)/(ending_srt_time - starting_time_given_srt)
118
+
119
+ multiply_proc = proc {|you|
120
+ ((you - starting_time_given_srt) * multiply_by_this_factor) + starting_time_actual
121
+ }
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+ bad_profanities = {'hell' => ['h...', :full_word],
152
+ 'g' +
153
+ 111.chr +
154
+ 100.chr => ['vain use', :partial_word, 'deity'], 'g' +
155
+ 111.chr +
156
+ 100.chr +
157
+ 's' => 'deitys',
158
+ 'meu deus' => 'l...',
159
+ 'lo' +
160
+ 'rd' => 'l...', 'da' +
161
+ 'mn' => 'd...',
162
+ 'f' +
163
+ 117.chr +
164
+ 99.chr +
165
+ 107.chr =>
166
+ 'f...',
167
+ 'allah' => 'all..',
168
+ 'bi' +
169
+ 'tc' + 104.chr => 'b....',
170
+ 'bas' +
171
+ 'ta' +
172
+ 'r' + 100.chr => 'ba.....',
173
+ ((arse = 'a' +
174
+ 's'*2)) => ['a..', :full_word],
175
+ arse + 'h' +
176
+ 'ole' => 'a..h...',
177
+ 'dieu' => ['deity', :full_word],
178
+ arse + 'w' +
179
+ 'ipe' => 'a..w...',
180
+ 'jes' +
181
+ 'u' + 's' => ['vain use', :partial_word, 'deity'],
182
+ 'chri' +
183
+ 'st'=> ['vain use', :full_word, 'deity'], # allow for christian[ity]
184
+ 'sh' +
185
+ 'i' + 't' => 'sh..',
186
+ 'cu' +
187
+ 'nt' => 'c...',
188
+ 'cock' +
189
+ 'su' +
190
+ 'cker' => 'cock......',
191
+ }
192
+
193
+
194
+ semi_bad_profanities = {}
195
+ ['moron', 'breast', 'idiot',
196
+ 'sex', 'genital',
197
+ 'boob',
198
+ 'tits',
199
+ 'make love', 'pen' +
200
+ 'is',
201
+ 'pu' +
202
+ 'ssy',
203
+ 'fart',
204
+ 'whore',
205
+ 'debauch',
206
+ 'making' +
207
+ ' love', 'love mak',
208
+ 'dumb', 'suck', 'piss', 'c' +
209
+ 'u' + 'nt',
210
+ 'd' + 'ick', 'vag' +
211
+ 'i' + 'na',
212
+ ].each{|name|
213
+ semi_bad_profanities[name] = name
214
+ }
215
+ semi_bad_profanities['bloody'] = 'bloo..'
216
+ semi_bad_profanities['crap'] = ['crap', :full_word]
217
+ semi_bad_profanities['butt'] = ['butt', :full_word]
218
+ # butter?
219
+
220
+ semi_bad_profanities.merge! extra_profanity_hash
221
+
222
+ all_profanity_combinationss = [convert_to_regexps(bad_profanities)]
223
+ if include_minor_profanities
224
+ all_profanity_combinationss += [convert_to_regexps(semi_bad_profanities)]
225
+ end
226
+
227
+ output = ''
228
+ entries = split_to_entries(subtitles)
229
+ for all_profanity_combinations in all_profanity_combinationss
230
+ output += "\n"
231
+ for entry in entries
232
+ text = entry.text
233
+ ts_begin = entry.beginning_time
234
+ ts_begin -= subtract_from_each_beginning_ts
235
+ ts_begin = multiply_proc.call(ts_begin)
236
+
237
+ ts_end = entry.ending_time
238
+ ts_end += add_to_end_each_ts
239
+ ts_end = multiply_proc.call(ts_end)
240
+ found_category = nil
241
+ for (profanity, category, sanitized) in all_profanity_combinations
242
+ if text =~ profanity
243
+ found_category = category
244
+ break
245
+ end
246
+ end
247
+
248
+ if found_category
249
+ # sanitize/euphemize the subtitle text for all profanities...
250
+ for all_profanity_combinations2 in all_profanity_combinationss
251
+ for (profanity, category, sanitized) in all_profanity_combinations2
252
+ text.gsub!(profanity, sanitized)
253
+ end
254
+ end
255
+
256
+ # because we now have duplicate's for the letter l/i, refactor [[[word]]] to just [word]
257
+ text.gsub!(/\[+/, '[')
258
+ text.gsub!(/\]+/, ']')
259
+ entry.text = text
260
+ add_single_line_minimized_text_from_multiline entry
261
+ text = text.gsub(/[\r\n]|\n/, ' ') # flatten up to 3 lines of text to just 1
262
+ ts_begin_human = EdlParser.translate_time_to_human_readable ts_begin, true
263
+ ts_end_human = EdlParser.translate_time_to_human_readable ts_end, true
264
+ unless output.contain? ts_begin_human # some previous profanity already found this line :P
265
+ output += %! "#{ts_begin_human}" , "#{ts_end_human}", "profanity", "#{found_category}", "#{text}",\n!
266
+ end
267
+ end
268
+ end
269
+ end
270
+ # update timestamps to be synchro'ed
271
+ for entry in entries
272
+ entry.beginning_time = multiply_proc.call(entry.beginning_time)
273
+ entry.ending_time = multiply_proc.call(entry.ending_time)
274
+ end
275
+ [output, entries]
276
+ end
277
+ end
278
+
279
+ if $0 == __FILE__
280
+ if ARGV.empty?
281
+ p 'syntax: [filename.srt | [--create-edl|--create-edl-including-minor-profanities] input_name.srt output_name.edl]'
282
+ exit
283
+ elsif ARGV[0].in? ['--create-edl', '--create-edl-including-minor-profanities']
284
+ require_relative 'mplayer_edl'
285
+ incoming_filename = ARGV[1]
286
+ include_minors = true if ARGV[0] == '--create-edl-including-minor-profanities'
287
+ mutes = SubtitleProfanityFinder.edl_output_from_string File.read(incoming_filename), {}, 0, 0, "00:00", "00:00", "10:00:00", "10:00:00", include_minors
288
+ specs = EdlParser.parse_string %!"mutes" => [#{mutes}]!
289
+ File.write(ARGV[2], MplayerEdl.convert_to_edl(specs))
290
+ puts "wrote to #{ARGV[2]}"
291
+ else
292
+ print SubtitleProfanityFinder.edl_output ARGV.first
293
+ end
294
+ end