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,23 @@
1
+ The design, not the idea.
2
+
3
+ OCR can work on internet or standalone players.
4
+ time elapsed "since the timestamp changed" on screen infers the more precise millisecond
5
+ you are at, for being able to skip, mute, overlay, apply overlaid transparent image/video more precisely.
6
+ You can grab the specific coordinates by precise location, or by iterating over windows, or by relative location to screen coordinates/window coordinates.
7
+ You can use the url to infer the title desired.
8
+ You can use user preferences to infer how to use each setting within the "EDL" by saving the user preference, and comparing it
9
+ against each entry in the EDL when you parse it.
10
+
11
+ It can mute by clicking a mute button, by accessing an API.
12
+ It can work by monitoring, using an API, the current playback time.
13
+
14
+ It can react to "seek" commands to coordinate position within EDL's.
15
+
16
+ Another invention: it can apply editing "commands" to a player that is playing back blu-ray discs (hardware or software), as originally described in other clearplay
17
+ patents, like US6889383 and those issued to them afterward.
18
+
19
+ You can get the specific digits by "absolute digit location" or by "OCR on the entire timestamp"
20
+
21
+ Could also playback using avisynth.
22
+
23
+ Can create edited files.
@@ -0,0 +1,32 @@
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
+
19
+ def add_any_bundled_gems_to_load_path
20
+ vendor_dir = File.dirname(__FILE__) + '/../vendor'
21
+ raise 'no vendor dir?' unless File.directory?(vendor_dir)
22
+ if File.directory? vendor_dir + '/cache'
23
+ Dir[vendor_dir + '/**/lib'].sort.reverse.each{|lib_dir| # prefers newer versioned copies of gems in case I have duplicates
24
+ $: << lib_dir
25
+ }
26
+ else
27
+ require 'rubygems'
28
+ # they'll need imagemagick installed, as well, currently
29
+ end
30
+ end
31
+
32
+ add_any_bundled_gems_to_load_path
@@ -0,0 +1,41 @@
1
+ require 'rautomation'
2
+ require_relative 'edl_parser'
3
+
4
+ class AutoWindowFinder
5
+
6
+ # when they select a file, it contains a...url say...
7
+ # so look for that url, with "this" child window class [?]
8
+ # so basically, if a browser window is "open" to such and such a url
9
+ # and it is mentioned in a file
10
+ # it should find it
11
+
12
+ def self.search_for_single_url_match regexp = /Chrome/
13
+ EdlParser.find_single_edit_list_matching(true) {|parsed|
14
+ if url = parsed["url"]
15
+ window = RAutomation::Window.new(:title => regexp)
16
+ if window.exist?
17
+ if window.text =~ Regexp.new(Regexp.escape url.gsub(/http(s|):\/\//, ""))
18
+ p 'got match' + url
19
+ true
20
+ else
21
+ false
22
+ end
23
+ end
24
+ end
25
+ }
26
+ end
27
+
28
+ def self.search_for_player_and_url_match player_root_dir
29
+ for filename in Dir[player_root_dir + '/*/*.txt']
30
+ settings = YAML.load_file filename
31
+ if regex = settings["window_title"] # assume regex :)
32
+ p 'searching for player regex', regex
33
+ if search_for_single_url_match regex # applies the regex X url
34
+ return filename
35
+ end
36
+ end
37
+ end
38
+ nil
39
+ end
40
+
41
+ end
@@ -0,0 +1,104 @@
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
+
19
+ if RUBY_PLATFORM !~ /java/
20
+ require_relative 'fake_blanker'
21
+ else
22
+
23
+ require 'java'
24
+
25
+ class Blanker
26
+ JFrame = javax.swing.JFrame
27
+ JLabel = javax.swing.JLabel
28
+
29
+ def self.startup
30
+ @fr = JFrame.new("Sensible Cinema blanker-outer overlay window")
31
+ @fr.default_close_operation = JFrame::EXIT_ON_CLOSE
32
+ @fr.set_size(2000, 2000) # ltodo better size ?
33
+ cp = @fr.getContentPane
34
+ cp.setBackground(java.awt.Color.black);
35
+
36
+ @label = JLabel.new
37
+ @label.set_text 'blanked'
38
+ @fr.add(@label)
39
+ @label.setForeground(java.awt.Color.white);
40
+ @label.repaint
41
+ @label.revalidate
42
+
43
+ @fr.set_resizable(false)
44
+ @fr.set_visible(true) # have to do this once, to ever see the thing
45
+ # lodo does this really speed things up to pre-create it? that icon is a bit ugly in the taskbar...
46
+ @fr.repaint
47
+ @fr.set_visible(false) # hide it to start
48
+ end
49
+
50
+ @@use_mouse = false
51
+ @@use_foreground_window_minimize = false
52
+ if @@use_foreground_window_minimize
53
+ require 'win32/screenshot'
54
+ SW_MINIMIZE = 6
55
+ end
56
+
57
+ def self.minimize_hwnd hwnd
58
+ Win32::Screenshot::BitmapMaker.show_window(hwnd, SW_MINIMIZE)
59
+ end
60
+
61
+ def self.restore_hwnd hwnd
62
+ Win32::Screenshot::BitmapMaker.restore(hwnd)
63
+ end
64
+
65
+ def self.blank_full_screen! seconds
66
+
67
+ if @@use_mouse
68
+ Mouse.single_click_left_mouse_button
69
+ elsif @@use_foreground_window_minimize
70
+ @foreground_hwnd ||= Win32::Screenshot::BitmapMaker.foreground_window
71
+ minimize_hwnd @foreground_hwnd
72
+ else
73
+ # somewhat hacky work around for doze: http://www.experts-exchange.com/Programming/Languages/Java/Q_22977145.html
74
+ @fr.setAlwaysOnTop(false)
75
+ @fr.setAlwaysOnTop(true)
76
+ @fr.set_location(0,0)
77
+ @fr.repaint # early paint, just in case that helps it pop up faster :)
78
+ if seconds
79
+ @label.set_text " #{seconds} s"
80
+ else
81
+ @label.set_text " Blank section"
82
+ end
83
+ end
84
+ end
85
+
86
+ def self.unblank_full_screen!
87
+ if @@use_mouse
88
+ Mouse.single_click_left_mouse_button
89
+ elsif @@use_foreground_window_minimize
90
+ restore_hwnd @foreground_hwnd
91
+ else
92
+ # just move it off screen...lodo
93
+ @fr.set_location(-2100, -2100)
94
+ @fr.repaint 0
95
+ end
96
+ end
97
+
98
+ def self.shutdown
99
+ @fr.dispose
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'os'
3
+ success = true
4
+
5
+ ENV['PATH'] = '/opt/rdp_project_local/bin/:' + ENV['PATH'] # macports' bin in first
6
+
7
+ module CheckInstalledMac
8
+
9
+ # should output an error message...
10
+ def self.check_for_installed name
11
+ # check for these with generic "does it run"
12
+
13
+ command = {"gocr" => "gocr --help", "convert" => "convert --help", "ffmpeg" => "ffmpeg -version", "mplayer" => "mplayer"}[name]
14
+
15
+ raise 'unknown ' + name unless command # sanity check
16
+
17
+ unless system("/opt/rdp_project_local/bin/#{command} 1>/dev/null 2>&1")
18
+ name = 'ImageMagick' if name == 'convert' # special case...
19
+ puts 'lacking dependency! Please install ' + name + ' by installing from the mac dependencies link from the website first'
20
+ false
21
+ else
22
+ true
23
+ end
24
+
25
+ end
26
+ end
27
+
28
+ if $0 == __FILE__
29
+ for name in ['gocr', 'convert', 'mplayer', 'ffmpeg'] do
30
+ if CheckInstalledMac.check_for_installed name
31
+ puts 'has dep:' + name
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ module ConvertThirtyFps
2
+
3
+ def self.from_thirty seconds_float
4
+ twentyNinePointNineSeven = 30000/1001.0 # 29.97
5
+ seconds_float * 30/twentyNinePointNineSeven
6
+ end
7
+
8
+ def self.from_twenty_nine_nine_seven seconds_float
9
+ twentyNinePointNineSeven = 30000/1001.0
10
+ seconds_float * twentyNinePointNineSeven/30
11
+ end
12
+
13
+ end
14
+
15
+ if $0 == __FILE__
16
+ p 'syntax: second to convert '
17
+ seconds = eval(ARGV[0] || "1000").to_f
18
+ p 'converted value from 30 to 29.97 is', ConvertThirtyFps.from_thirty(seconds) # should be bigger...
19
+ p 'converted value from 29.97 to 30 is', ConvertThirtyFps.from_twenty_nine_nine_seven(seconds)
20
+ end
@@ -0,0 +1,387 @@
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
+
19
+ require 'sane'
20
+ require_relative 'convert_thirty_fps'
21
+
22
+ class EdlParser
23
+
24
+ def self.on_any_file_changed_single_cached_thread &this_block
25
+ raise unless this_block
26
+ get_files_hash = proc {
27
+ glob = EDL_DIR + '/../**/*'
28
+ Dir[glob].map{|f|
29
+ [f, File.mtime(f)]
30
+ }.sort
31
+ }
32
+ old_value = get_files_hash.call
33
+ @@checking_thread ||= Thread.new {
34
+ loop {
35
+ current_value = get_files_hash.call
36
+ if current_value != old_value
37
+ print 'detected some file was changed! Re-parsing to update...'
38
+ old_value = current_value
39
+ this_block.call
40
+ puts 'done.'
41
+ end
42
+ sleep 2 # 0.02 for size 70, so...hopefully this is ok...
43
+ }
44
+ }
45
+ end
46
+
47
+ # this one is 1:01:02.0 => 36692.0
48
+ # its reverse is this: translate_time_to_human_readable
49
+ def self.translate_string_to_seconds s
50
+ # might actually already be a float, or int, depending on the yaml
51
+ # int for 8 => 9 and also for 1:09 => 1:10
52
+ if s.is_a? Numeric
53
+ return s.to_f # easy out.
54
+ end
55
+
56
+ s = s.strip
57
+ # s is like 1:01:02.0
58
+ total = 0.0
59
+ seconds = nil
60
+ seconds = s.split(":")[-1]
61
+ raise 'does not look like a timestamp? ' + seconds.inspect unless seconds =~ /^\d+(|[,.]\d+)$/
62
+ seconds.gsub!(',', '.')
63
+ total += seconds.to_f
64
+ minutes = s.split(":")[-2] || "0"
65
+ total += 60 * minutes.to_i
66
+ hours = s.split(":")[-3] || "0"
67
+ total += 60* 60 * hours.to_i
68
+ total
69
+ end
70
+
71
+ EDL_DIR = File.expand_path(__DIR__ + "/../zamples/edit_decision_lists/dvds")
72
+
73
+ if File::ALT_SEPARATOR
74
+ EDL_DIR.gsub! File::SEPARATOR, File::ALT_SEPARATOR # to_filename...
75
+ end
76
+
77
+ # returns {"mutes" => [["00:00", "00:00", string1, string2, ...], ...], "blank_outs" -> [...], "url" => ...}
78
+ def self.parse_file filename, expand = true
79
+ output = parse_string File.read(filename), filename, []
80
+ # now respect a few options
81
+ if relative = output["take_from_relative_file"]
82
+ new_filename = File.dirname(filename) + '/' + relative
83
+ new_input = parse_file new_filename
84
+ output.merge! new_input
85
+ end
86
+
87
+ require_relative 'gui/dependencies' # for download methods...
88
+
89
+ if expand
90
+
91
+ if output["from_url"] # replacement
92
+ downloaded = SensibleSwing::MainWindow.download_to_string(output["from_url"])
93
+ output = parse_string downloaded # full replacement
94
+ end
95
+
96
+ if imdb_id = output["imdb_id"]
97
+ parse_imdb output, imdb_id
98
+ end
99
+ end
100
+ output
101
+ end
102
+
103
+ def self.parse_imdb output, imdb_id
104
+ require_relative 'convert_thirty_fps'
105
+ url = "http://www.imdb.com/title/#{imdb_id}/parentalguide"
106
+ all = SensibleSwing::MainWindow.download_to_string(url)
107
+
108
+ header, violence_word, violence_section, profanity_word, profanity_section, alcohol_word, alcohol_section, frightening_word, frightening_section =
109
+ sections = all.split(/<span>(Violence|Profanity|Alcohol|Frightening)/)
110
+ header = sections.shift
111
+ all ={}
112
+ while(!sections.empty?) # my klugey to_hash method
113
+ word_type = sections.shift
114
+ settings = sections.shift
115
+ assert word_type.in? ['Violence', 'Profanity', 'Alcohol', 'Frightening']
116
+ all[word_type] = settings
117
+ end
118
+ # blank_outs or mutes for each...
119
+ # TODO make the -> optional
120
+ split_into_timestamps = /([\d:]+(?:\.\d+|))\W*-&gt;\W*([\d:]+(?:\.\d+|))([^\d\n]+)/
121
+ for type, settings in all
122
+ settings.scan(split_into_timestamps) do |begin_ts, end_ts, description|
123
+ puts "parsing from wiki imdb entry violence: #{begin_ts} #{end_ts} #{description} #{type}"
124
+ start_seconds = translate_string_to_seconds begin_ts
125
+ end_seconds = translate_string_to_seconds end_ts
126
+ # convert from 30 to 29.97 fps ... we presume ...
127
+ start_seconds = ConvertThirtyFps.from_twenty_nine_nine_seven start_seconds
128
+ start_seconds = ("%.02f" % start_seconds).to_f # round
129
+ start_seconds = translate_time_to_human_readable start_seconds, true
130
+ end_seconds = ConvertThirtyFps.from_twenty_nine_nine_seven end_seconds
131
+ end_seconds = ("%.02f" % end_seconds).to_f # round
132
+ end_seconds = translate_time_to_human_readable end_seconds, true
133
+ p end_seconds
134
+ if type == 'Profanity'
135
+ output['mutes'] << [start_seconds, end_seconds]
136
+ else
137
+ output['blank_outs'] << [start_seconds, end_seconds]
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ private
144
+
145
+ def self.download full_url, to_here
146
+ ::SwingHelpers::MainWindow.download full_url, to_here
147
+ end
148
+
149
+ # better eye-ball these before letting people run them, eh? TODO
150
+ # but I couldn't think of any other way to parse the files tho
151
+ def self.parse_string string, filename = nil, ok_categories_array = []
152
+ string = '{' + string + "\n}"
153
+ begin
154
+ if filename
155
+ raw = eval(string, binding, filename, 0)
156
+ else
157
+ raw = eval string
158
+ end
159
+ rescue Exception => e
160
+ string.strip.lines.to_a[0..-3].each_with_index{|l, idx| # last line doesn't need a comma check
161
+ orig_line = l
162
+ l = l.split('#')[0]
163
+ l = l.strip
164
+
165
+ unless l.empty?
166
+ # todo strip off # comments at the end of lines too...
167
+ end_char = l[-1..-1]
168
+ if !end_char.in? ['[', '{'] # these are probably ok...
169
+ puts "warning: #{File.basename filename} line #{idx} might be bad: (maybe needs comma after?) " + l unless end_char == ','
170
+ end
171
+ end
172
+ }
173
+ raise SyntaxError.new(e.to_s) # to_s as a workaround for jruby #6353
174
+ end
175
+
176
+ raise SyntaxError.new("maybe missing quotation marks somewhere?" + string) if raw.keys.contain?(nil)
177
+
178
+ # mutes and blank_outs need to be special parsed into arrays...
179
+ mutes = raw["mutes"] || []
180
+ blanks = raw["blank_outs"] || []
181
+ raw["mutes"] = convert_to_timestamp_arrays(mutes, ok_categories_array)
182
+ raw["blank_outs"] = convert_to_timestamp_arrays(blanks, ok_categories_array)
183
+ raw
184
+ end
185
+
186
+ # converts "blanks" => ["00:00:00", "00", "reason", "01", "01", "02", "02"] into sane arrays, also filters based on category, though not used in production
187
+ def self.convert_to_timestamp_arrays array, ok_categories_array
188
+ out = []
189
+ while(single_element = extract_entry!(array))
190
+ # assume that it (could be, at least) start_time, end_time, category, number
191
+ category = single_element[-2]
192
+ category_number = single_element[-1]
193
+ include = true
194
+ if ok_categories_array.index([category, category_number])
195
+ include = false
196
+ elsif ok_categories_array.index([category])
197
+ include = false
198
+ elsif ok_categories_array.detect{|cat, setting| setting.is_a? Fixnum}
199
+ for cat, setting in ok_categories_array
200
+ if cat == category && setting.is_a?(Fixnum)
201
+ # check for a number for filtering out based on level
202
+ if category_number.to_i.to_s == category_number
203
+ as_number = category_number.to_i
204
+ if as_number < setting
205
+ include = false
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ end
212
+ out << single_element if include
213
+ end
214
+ out
215
+ end
216
+
217
+ # TimeStamp = /(^\d+:\d\d[\d:\.]*$|\d+)/ # this one also allows for 4444 [?] and also weirdness like "don't kill the nice butterfly 2!" ...
218
+ TimeStamp = /^\s*(\d+:\d\d[\d:\.]*|\d+\.\d+)\s*$/ # allow 00:00:00 00:00:00.0 1222.4 " 2:04 "
219
+ # disallow's 1905 too but elsewhere in the code
220
+
221
+ def self.extract_entry! from_this
222
+ return nil if from_this.length == 0
223
+ # two digits, then whatever else you see, that's not a digit...
224
+ out = from_this.shift(2)
225
+ out.each{|d|
226
+ unless d =~ TimeStamp
227
+ raise SyntaxError.new('non timestamp? ' + d.inspect)
228
+ end
229
+ }
230
+ while(from_this[0] && from_this[0] !~ TimeStamp)
231
+ raise SyntaxError.new('straight digits not allowed use 1000.0 instead') if from_this[0] =~ /^\d+$/
232
+ out << from_this.shift
233
+ end
234
+ out
235
+ end
236
+
237
+ public
238
+
239
+ # called later, from external files
240
+ # divides up mutes and blanks so that they don't overlap, preferring blanks over mutes
241
+ # returns it like [[start,end,type], [s,e,t]...] type like either :blank and :mute
242
+ # [ [70.0, 73.0, :blank], [378.0, 379.1, :mute], ... ]
243
+ def self.convert_incoming_to_split_sectors incoming, add_this_to_all_ends = 0, subtract_this_from_beginnings = 0, splits = [], subtract_this_from_ends = 0
244
+ raise if subtract_this_from_beginnings < 0
245
+ raise if add_this_to_all_ends < 0
246
+ raise if subtract_this_from_ends < 0
247
+ add_this_to_all_ends -= subtract_this_from_ends # now we allow negative :)
248
+ # raise if splits.size > 0 # just ignore them for now
249
+ mutes = incoming["mutes"] || {}
250
+ blanks = incoming["blank_outs"] || {}
251
+ mutes = mutes.map{|k, v| [k,v,:mute]}
252
+ blanks = blanks.map{|k, v| [k,v,:blank]}
253
+ combined = (mutes+blanks).map{|s,e,type| [translate_string_to_seconds(s), translate_string_to_seconds(e), type]}.sort
254
+
255
+ # detect any weirdness...
256
+ previous = nil
257
+ combined.map!{ |current|
258
+ s,e,type = current
259
+ if e < s || !s || !e || !type
260
+ p caller
261
+ raise SyntaxError.new("detected an end before a start or other weirdness: #{s} > #{e}")
262
+ end
263
+ if previous
264
+ ps, previous_end, pt = previous
265
+ if (s < previous_end)
266
+ raise SyntaxError.new("detected an overlap current #{s} < #{previous_end} of current: #{current.join(' ')} previous: #{previous.join(' ')}")
267
+ end
268
+ end
269
+ previous = current
270
+ # do the math later to allow for ones that barely hit into each other 1.0 2.0, 2.0 3.0
271
+ [s-subtract_this_from_beginnings, e+add_this_to_all_ends,type]
272
+ }
273
+ combined
274
+ end
275
+
276
+
277
+ # its reverse: translate_string_to_seconds
278
+ def self.translate_time_to_human_readable seconds, force_hour_stamp = false
279
+ # 3600 => "1:00:00"
280
+ out = ''
281
+ hours = seconds.to_i / 3600
282
+ if hours > 0 || force_hour_stamp
283
+ out << "%d" % hours
284
+ out << ":"
285
+ end
286
+ seconds = seconds - hours*3600
287
+ minutes = seconds.to_i / 60
288
+ out << "%02d" % minutes
289
+ seconds = seconds - minutes * 60
290
+ out << ":"
291
+
292
+ # avoid an ugly .0 at the end
293
+ # if seconds == seconds.to_i
294
+ # out << "%02d" % seconds
295
+ # else
296
+ out << "%05.2f" % seconds # man that printf syntax is tricky...
297
+ # end
298
+
299
+ end
300
+
301
+ def self.all_edl_files_parsed use_all_not_just_dvds
302
+ dir = EDL_DIR
303
+ dir += "/.." if use_all_not_just_dvds
304
+ Dir[dir + '/**/*.txt'].map{|filename|
305
+ begin
306
+ parsed = parse_file(filename)
307
+ [filename, parsed]
308
+ rescue SyntaxError => e
309
+ # ignore poorly formed edit lists for the auto choose phase...
310
+ puts 'warning, unable to parse a file:' + filename + " " + e.to_s
311
+ nil
312
+ end
313
+ }.compact
314
+ end
315
+
316
+ # returns single matching filename
317
+ # requires a block
318
+ def self.find_single_edit_list_matching use_all_not_just_dvd_dir = false, return_first_if_there_are_several = false
319
+ matching = all_edl_files_parsed(use_all_not_just_dvd_dir).map{|filename, parsed|
320
+ yield(parsed) ? filename : nil
321
+ }.compact
322
+ if matching.length == 1
323
+ file = matching[0]
324
+ file
325
+ elsif matching.length > 1
326
+ p "found multiple matches for media? #{matching.inspect}"
327
+ if return_first_if_there_are_several
328
+ matching[0]
329
+ else
330
+ nil
331
+ end
332
+ else
333
+ nil
334
+ end
335
+ end
336
+
337
+ def self.single_edit_list_matches_dvd dvd_id, return_first_if_there_are_several = false
338
+ return nil unless dvd_id
339
+ find_single_edit_list_matching(false, return_first_if_there_are_several) {|parsed|
340
+ parsed["disk_unique_id"] == dvd_id
341
+ }
342
+ end
343
+
344
+ def self.convert_to_dvd_nav_times combined, start_type, start_mpeg_time, dvd_nav_packet_offsets, time_multiplier
345
+ start_dvdnav_time = dvd_nav_packet_offsets[1] - dvd_nav_packet_offsets[0]
346
+ raise unless start_type == 'dvd_start_offset' # for now :P
347
+ out = []
348
+ add_this_to_all_of_them = start_dvdnav_time - start_mpeg_time
349
+ #[[70.0, 73.0, :blank], [378.0, 379.1, :mute]]
350
+ for start, endy, type in combined
351
+ if time_multiplier == 30
352
+ # ok
353
+ elsif time_multiplier == 29.97
354
+ start = ConvertThirtyFps.from_twenty_nine_nine_seven start
355
+ endy = ConvertThirtyFps.from_twenty_nine_nine_seven endy
356
+ else
357
+ raise time_multiplier
358
+ end
359
+ start += start_dvdnav_time
360
+ endy += start_dvdnav_time
361
+ out << [start, endy, type]
362
+ end
363
+ out
364
+ end
365
+
366
+ end
367
+
368
+ # == 1.8.7 1.9 Symbol compat
369
+
370
+ class Symbol
371
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Symbol.html]
372
+ def <=>(with)
373
+ return nil unless with.is_a? Symbol
374
+ to_s <=> with.to_s
375
+ end unless method_defined? :"<=>"
376
+ end
377
+
378
+ if $0 == __FILE__
379
+ p 'syntax: filename'
380
+ require 'rubygems'
381
+ require 'sane'
382
+ parsed = EdlParser.parse_file(*ARGV)
383
+ p 'parsed well'
384
+ p parsed
385
+ require 'yaml'
386
+ print YAML.dump parsed
387
+ end