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
@@ -0,0 +1,244 @@
1
+ module SensibleSwing
2
+
3
+ class MainWindow
4
+
5
+ def add_options_that_use_local_files
6
+ check_for_file_manipulation_dependencies
7
+ add_text_line 'These are Create Options that operate on a file:'
8
+
9
+ @preview_section = new_jbutton( "Preview a certain time frame (edited)" )
10
+ @preview_section.tool_tip = <<-EOL
11
+ This allows you to preview an edit easily.
12
+ It is the equivalent of saying \"watch this file edited from exactly minute x second y to minute z second q"
13
+ Typically if you want to test an edit, you can start a few seconds before, and end a few seconds after it, to test it precisely.
14
+ EOL
15
+ @preview_section.on_clicked {
16
+ do_create_edited_copy_via_file true
17
+ }
18
+
19
+ @preview_section_unedited = new_jbutton("Preview a certain time frame (unedited)" )
20
+ @preview_section.tool_tip = "Allows you to view a certain time frame unedited (ex: 10:00 to 10:05), so you can narrow down to pinpoint where questionable scenes are, etc. This is the only way to view a specific scene if there are not cuts within that scene yet."
21
+ @preview_section_unedited.on_clicked {
22
+ do_create_edited_copy_via_file true, false, true
23
+ }
24
+
25
+ @rerun_preview = new_jbutton( "Re-run most recently watched previewed time frame" )
26
+ @rerun_preview.tool_tip = "This will re-run the preview that you most recently performed. Great for checking to see if you last edits were successful or not."
27
+ @rerun_preview.on_clicked {
28
+ repeat_last_copy_dvd_to_hard_drive
29
+ }
30
+
31
+ # I think this is still useful...
32
+ @fast_preview = new_jbutton("fast preview EDL from fulli file (smplayer EDL)")
33
+ @fast_preview.tool_tip = <<-EOL
34
+ Plays smplayer on a file with an EDL.
35
+ This gives you a rough estimate to see if your edits are accurate, and is really fast to seek, etc.
36
+ This is useful because you can't use mplayer on a DVD for accurate timestamps if it has any
37
+ timestamp splits in it [because some DVD's are buggy]
38
+ EOL
39
+ @fast_preview.on_clicked {
40
+ success, wrote_to_here_fulli = do_create_edited_copy_via_file false, true
41
+ sleep 0.5 # lodo take out ???
42
+ background_thread.join if background_thread # let it write out the original fulli, if necessary [?]
43
+ nice_file = wrote_to_here_fulli
44
+ run_smplayer_blocking nice_file, nil, "-edl #{normalize_path EdlTempFile}", false, true, false, nil
45
+ }
46
+ end
47
+
48
+
49
+ def do_create_edited_copy_via_file should_prompt_for_start_and_end_times, exit_early_if_fulli_exists = false, watch_unedited = false
50
+ drive_or_file, dvd_volume_name, dvd_id, edit_list_path, descriptors = choose_dvd_or_file_and_edl_for_it
51
+
52
+ descriptors = parse_edl(edit_list_path)
53
+ if watch_unedited
54
+ # reset them
55
+ descriptors['mutes'] = descriptors['blank_outs'] = []
56
+ end
57
+
58
+ # LODO allow for spaces in the save_to filename
59
+ if should_prompt_for_start_and_end_times
60
+ start_time, end_time = get_start_stop_times_strings
61
+ end
62
+ dvd_friendly_name = descriptors['name']
63
+ unless dvd_friendly_name
64
+ drive_or_file, dvd_volume_name, dvd_id, edit_list_path, descriptors = choose_dvd_or_file_and_edl_for_it
65
+ descriptors = parse_edl(edit_list_path)
66
+ raise 'no dvd name in EDL?' + edit_list_path + File.read(edit_list_path)
67
+ end
68
+
69
+ dvd_title_track = get_title_track_string(descriptors)
70
+ if dvd_id == NonDvd
71
+ file_from = drive_or_file
72
+ else
73
+ file_from = get_ripped_filename_once dvd_friendly_name, dvd_title_track # we don't even care about the drive letter anymore...
74
+ end
75
+
76
+ sanity_check_file file_from
77
+
78
+ save_to_edited = get_save_to_filename_from_user dvd_friendly_name
79
+ fulli = MencoderWrapper.calculate_fulli_filename save_to_edited
80
+ if exit_early_if_fulli_exists
81
+ if fulli_dot_done_file_exists? save_to_edited
82
+ return [true, fulli]
83
+ end
84
+ # make it create a dummy response file for us :)
85
+ start_time = "00:00"
86
+ end_time = "00:01"
87
+ end
88
+
89
+ if !fulli_dot_done_file_exists? save_to_edited
90
+ show_non_blocking_message_dialog "Warning, the first pass through when editing file-wise, Sensible Cinema\nfirst needs to create a large temporary file that it can divide up easily.\nThis takes awhile, so you may need to get comfortable."
91
+ end
92
+
93
+ require_deletion_entry = true unless watch_unedited
94
+ should_run_mplayer_after = should_prompt_for_start_and_end_times || exit_early_if_fulli_exists
95
+ generate_and_run_bat_file save_to_edited, edit_list_path, descriptors, file_from, dvd_friendly_name, start_time, end_time, dvd_title_track, should_run_mplayer_after, require_deletion_entry
96
+ [false, fulli] # false means it's running in a background thread :P
97
+ end
98
+
99
+ def sanity_check_file filename
100
+ out = `ffmpeg -i #{filename} 2>&1`
101
+ print out
102
+ unless out =~ /Duration.*start: 0.00/ || out =~ /Duration.*start: 600/
103
+ show_blocking_message_dialog 'file\'s typically have the movie start at zero, this one doesn\'t? Please report.' + out
104
+ raise # give up, as otherwise we're 0.3 off, I think...hmm...
105
+ end
106
+ if filename =~ /\.mkv/i
107
+ show_blocking_message_dialog "warning .mkv files from makemkv have been known to be off timing wise, please convert to a .ts file using tsmuxer first if it did come from makemkv"
108
+ else
109
+ if filename !~ /\.(ts|mpg|mpeg)$/i
110
+ show_blocking_message_dialog("warning: file #{filename} is not a .mpg or .ts file--conversion may not work properly all the way [produce a truncated file], but we can try it if you want...")
111
+ end
112
+ end
113
+ end
114
+
115
+ def repeat_last_copy_dvd_to_hard_drive
116
+ generate_and_run_bat_file(*LocalStorage['last_params'])
117
+ end
118
+
119
+ def get_ripped_filename_once dvd_title, dvd_title_track
120
+ @_get_ripped_filename_once ||=
121
+ begin
122
+ new_existing_file_selector_and_select_file "Please choose the file that is your ripped equivalent of #{dvd_title} (title track #{dvd_title_track}) (.mpg or .ts--see file documentation/how_to_get_files_from_dvd.txt)"
123
+ end
124
+ end
125
+
126
+ def get_save_to_filename_from_user dvd_title
127
+ @_get_save_to_filename_from_user ||=
128
+ begin
129
+ save_to_file_name = dvd_title + ' edited version'
130
+ save_to_file_name = save_to_file_name.gsub(' ', '_').gsub( /\W/, '') + ".avi" # no punctuation or spaces for now, to not complicate...
131
+ save_to = new_nonexisting_filechooser_and_go "Pick where to save #{dvd_title} edited version to", nil, get_drive_with_most_space_with_slash + save_to_file_name
132
+ raise 'no spaces allowed yet' if save_to =~ / /
133
+ begin
134
+ a = File.open(File.dirname(save_to) + "/test_file_to_see_if_we_have_permission_to_write_to_this_folder", "w")
135
+ a.close
136
+ File.delete a.path
137
+ rescue Errno::EACCES => e
138
+ show_blocking_message_dialog "unable to write to that directory, please pick again: " + e.to_s
139
+ raise 'pick again!'
140
+ end
141
+ freespace = get_freespace(save_to)
142
+ if freespace < 8_000_000_000
143
+ show_blocking_message_dialog("Warning: there may not be enough space on the disk for #{save_to}
144
+ (depending on DVD size, you may need around 10G free--you have #{freespace/1_000_000_000}GB free). Click OK to continue.")
145
+ end
146
+ save_to.gsub(/\.avi$/, '')
147
+ end
148
+ end
149
+
150
+ def fulli_dot_done_file_exists? save_to_edited
151
+ fulli = MencoderWrapper.calculate_fulli_filename save_to_edited
152
+ File.exist?(fulli + ".done")
153
+ end
154
+
155
+ # to make it stubbable :)
156
+ def get_mencoder_commands descriptors, file_from, save_to, start_time, end_time, dvd_title_track, require_deletion_entry
157
+ delete_partials = true unless start_time # in case anybody wants to look really really close for now
158
+ MencoderWrapper.get_bat_commands descriptors, file_from, save_to, start_time, end_time, dvd_title_track, delete_partials, require_deletion_entry
159
+ end
160
+
161
+ def generate_and_run_bat_file save_to, edit_list_path, descriptors, file_from, dvd_title, start_time, end_time, dvd_title_track, run_mplayer, require_deletion_entry
162
+ LocalStorage['last_params'] = [save_to, edit_list_path, descriptors, file_from, dvd_title, start_time, end_time, dvd_title_track, run_mplayer, require_deletion_entry]
163
+ begin
164
+ commands = get_mencoder_commands descriptors, file_from, save_to, start_time, end_time, dvd_title_track, require_deletion_entry
165
+ rescue MencoderWrapper::TimingError => e
166
+ show_blocking_message_dialog("Appears you chose a time frame with no deletion segment in it--please try again:" + e)
167
+ return
168
+ rescue Errno::EACCES => e
169
+ show_blocking_message_dialog("Appears a file on the system is locked: perhaps you need to close down some instance of mplayer?" + e)
170
+ return
171
+ end
172
+ temp_dir = Dir.tmpdir
173
+ temp_file = temp_dir + '/vlc.temp.bat'
174
+ File.write(temp_file, commands)
175
+ popup_message = <<-EOL
176
+ Applying EDL #{File.basename edit_list_path}
177
+ to movie file #{file_from} (#{dvd_title}).
178
+ Saving to #{save_to}.
179
+ EOL
180
+ if !fulli_dot_done_file_exists?(save_to)
181
+ popup_message += "This will take quite awhile (several hours, depending on movie size), \nsince it needs to first create an intermediate file for more accurate splitting.\nit will prompt you with a chime noise when it is done.\n
182
+ You can close this window and minimize sensible cinema \nto continue using your computer while it runs in the background.\nYou can see progress via the progress bar.\n"
183
+ end
184
+
185
+ if !start_time
186
+ # assume a full run..
187
+ popup_message += <<-EOL
188
+ NB that the created file will be playable only with VLC (possibly also with smplayer),
189
+ but probably not with windows media player.
190
+ EOL
191
+ end
192
+
193
+ popup = show_non_blocking_message_dialog(popup_message, "OK")
194
+
195
+ # allow our popups to still be serviced while it is running
196
+ @background_thread = Thread.new { run_batch_file_commands_and_use_output_somehow commands, save_to, file_from, run_mplayer }
197
+ when_thread_done(@background_thread) { popup.dispose }
198
+ # LODO warn if they will overwrite a file in the end...
199
+ end
200
+
201
+ def run_batch_file_commands_and_use_output_somehow batch_commands, save_to, file_from, run_mplayer_after_done
202
+ @buttons.each{|b| b.set_enabled false}
203
+ success = true
204
+ lines = batch_commands.lines.to_a
205
+ total_size = lines.length.to_f
206
+ @progress_bar.visible=true
207
+ @progress_bar.set_value(10) # start at 10% always, so they can see something.
208
+ lines.each_with_index{|line, idx|
209
+ if success
210
+ puts "running #{line}"
211
+ success = system_blocking(line, true)
212
+ if !success
213
+ puts "\n", 'line failed: ' + line + "\n" + ' see troubleshooting section in README.txt file! ignoring further processing commands...'
214
+ end
215
+ end
216
+ @progress_bar.set_value(10 + idx/total_size*90)
217
+ }
218
+ @progress_bar.visible=false
219
+ @buttons.each{|b| b.set_enabled true}
220
+ if success
221
+ saved_to = save_to + '.avi'
222
+ if run_mplayer_after_done
223
+ run_smplayer_non_blocking saved_to, nil, '', false, false, true, nil
224
+ else
225
+ size_original = File.size(file_from)
226
+ size_edited_version = File.size(saved_to)
227
+ if size_edited_version < (size_original*0.5)
228
+ show_blocking_message_dialog("Warning: file sizes differs by more than 50%--it's possible that transcoding failed somehow. Orig: #{size_original} edited: #{size_edited_version}")
229
+ end
230
+ show_in_explorer saved_to
231
+ PlayAudio.new(File.expand_path(File.dirname(__FILE__)) + "/../../vendor/music.wav").start # let it finish on its own :P
232
+ msg = "Done--you may now watch file\n #{saved_to}\n in VLC player (or possibly smplayer)"
233
+ puts msg # for being able to tell it's done on the command line
234
+ show_blocking_message_dialog msg
235
+ end
236
+ else
237
+ SwingHelpers.show_blocking_message_dialog "Failed--please examine console output and report back!\nAlso consult the documentation/troubleshooting file.", "Failed", JOptionPane::ERROR_MESSAGE
238
+ end
239
+ end
240
+
241
+
242
+
243
+ end
244
+ end
@@ -0,0 +1,565 @@
1
+ module SensibleSwing
2
+
3
+ class MainWindow
4
+
5
+ def open_edl_file_when_done thred, filename
6
+ Thread.new {
7
+ thred.join
8
+ open_file_to_edit_it filename
9
+ }
10
+ end
11
+
12
+ def setup_advanced_buttons
13
+
14
+ add_text_line 'Normal playback Options:'
15
+ new_jbutton("Display Standard Playback Options") do
16
+ window = new_child_window
17
+ window.setup_normal_buttons
18
+ end
19
+
20
+ add_text_line 'Create: Edit Decision List File Options:'
21
+
22
+ @open_current = new_jbutton("Edit/Open EDL for currently inserted DVD") do
23
+ drive, volume_name, dvd_id = choose_dvd_drive_or_file true # require a real DVD disk :)
24
+ edit_list_path = EdlParser.single_edit_list_matches_dvd(dvd_id)
25
+ if edit_list_path
26
+ open_file_to_edit_it edit_list_path
27
+ else
28
+ show_blocking_message_dialog "EDL for this dvd doesn't exist yet, maybe create it first? #{volume_name}"
29
+ end
30
+ end
31
+
32
+ create_new_edl_for_current_dvd_text = "Create new Edit List for currently inserted DVD"
33
+ @create_new_edl_for_current_dvd = new_jbutton(create_new_edl_for_current_dvd_text,
34
+ "If your DVD doesn't have an EDL created for it, this will be your first step--create an EDL file for it.")
35
+ @create_new_edl_for_current_dvd.on_clicked do
36
+ drive, volume_name, dvd_id = choose_dvd_drive_or_file true # require a real DVD disk :)
37
+ edit_list_path = EdlParser.single_edit_list_matches_dvd(dvd_id, true)
38
+ if edit_list_path
39
+ if show_select_buttons_prompt('It appears that one or more EDL\'s exist for this DVD already--create another?', {}) == :no
40
+ raise 'aborting'
41
+ end
42
+ end
43
+ create_brand_new_dvd_edl
44
+ update_currently_inserted_dvd_list # notify them that files have changed...lodo is there a better way?
45
+ end
46
+
47
+ add_callback_for_dvd_edl_present { |disk_available, edl_available|
48
+ @open_current.set_enabled edl_available
49
+ @create_new_edl_for_current_dvd.set_enabled disk_available
50
+ if edl_available
51
+ @create_new_edl_for_current_dvd.text= create_new_edl_for_current_dvd_text + " [yours already has one!]"
52
+ else
53
+ if disk_available
54
+ @create_new_edl_for_current_dvd.text= create_new_edl_for_current_dvd_text + " [doesn't have one yet!]"
55
+ else
56
+ @create_new_edl_for_current_dvd.text= create_new_edl_for_current_dvd_text + " [no disk inserted!]"
57
+ end
58
+ end
59
+ }
60
+
61
+ @parse_srt = new_jbutton("Scan a subtitle file (.srt) to detect profanity timestamps automatically" )
62
+ @parse_srt.tool_tip = <<-EOL
63
+ You can download a .srt file and use it to programmatically search for the location of various profanities.
64
+ Basically download it from opensubtitles.org (or engsub.net et al),
65
+ (for opensubtitles.org enter dvd title in the search box, click on a result, click one from the list with an English flag,
66
+ then choose 'Download(zip)', then unzip the file)
67
+ NB that you'll want/need to *carefully* double check your subtitle file for accuracy. Here's how:
68
+ Now carefully compare a beginning timestamp in it with the actual words in the .srt file
69
+ with the actual DVD.
70
+ (see the button "Watch DVD unedited (realtime mplayer)")
71
+ (smplayer can kind of do it, too, play it, hit the 'o' button to display
72
+ the OSD timestamp, then go to just before the verbiage,
73
+ and hit the '.' key until a subtitle very first appears.
74
+ Next convert that number to 29.97 fps (using the button for that).
75
+ EOL
76
+
77
+ @parse_srt.on_clicked do
78
+
79
+ srt_filename = new_existing_file_selector_and_select_file("Pick srt file to scan for profanities [may need to download .srt file first]:", File.expand_path('~'))
80
+ if(srt_filename =~ /utf16/) # from subrip sometimes
81
+ show_blocking_message_dialog "warning--filename #{srt_filename} may be in utf16, which we don't yet parse"
82
+ end
83
+ if srt_filename =~ /\.sub$/i
84
+ show_blocking_message_dialog "warning--file has to be in Subrip [.srt] format, and yours might be in .sub format, which is incompatible"
85
+ end
86
+ # TODO nuke, or do I use them for the 600.0 stuff?
87
+ add_to_beginning = "0.0"#get_user_input("How much time to subtract from the beginning of every subtitle entry (ex: (1:00,1:01) becomes (0:59,1:01))", "0.0")
88
+ add_to_end = "0.0"#get_user_input("How much time to add to the end of every subtitle entry (ex: (1:00,1:04) becomes (1:00,1:05))", "0.0")
89
+
90
+ if show_select_buttons_prompt("Sometimes subtitle files' time signatures don't match precisely with the video.\nWould you like to enter some information to allow it to synchronize the timestamps?\n (on the final pass you should do this, even if it already matches well, for future information' sake)") == :yes
91
+ with_autoclose_message("parsing srt file...") do
92
+ parsed_profanities, euphemized_synchronized_entries = SubtitleProfanityFinder.edl_output_from_string File.read(srt_filename), {}, 0, 0, 0, 0, 3000, 3000
93
+ write_subs_to_file euphemized_filename = EdlTempFile + '.euphemized.srt.txt', euphemized_synchronized_entries
94
+ open_file_to_edit_it euphemized_filename
95
+ sleep 0.5 # let it open in TextEdit/Notepad first...
96
+ bring_to_front
97
+ end
98
+
99
+ if show_select_buttons_prompt("Would you like to start playing the movie in mplayer, to be able to search for subtitle timestamp times [you probably do...]?\n") == :yes
100
+ Thread.new { play_dvd_smplayer_unedited true }
101
+ show_blocking_message_dialog "ok--use the arrow keys and pgdown/pgup to search/scan, and then '.' to pinpoint a precise subtitle start time within mplayer.\nYou will be prompted for a beginning and starting timestamp time."
102
+ end
103
+ all_entries = SubtitleProfanityFinder.split_to_entries File.read(srt_filename)
104
+ display_and_raise "unable to parse subtitle file?" unless all_entries.size > 10
105
+
106
+ start_text = all_entries[0].single_line_text
107
+ start_srt_time = all_entries[0].beginning_time
108
+ human_start = EdlParser.translate_time_to_human_readable(start_srt_time)
109
+ start_movie_ts = get_user_input("Enter beginning timestamp within the movie itself for when the subtitle \"#{start_text}\"\nfirst frame the subtitle appears on the on screen display (possibly near #{human_start})")
110
+ start_movie_time = EdlParser.translate_string_to_seconds start_movie_ts
111
+ if(show_select_buttons_prompt 'Would you like to select an ending timestamp at the end or 3/4 mark of the movie [end can be a spoiler at times]?', :yes => 'very end of movie', :no => '3/4 of the way into movie') == :yes
112
+ end_entry = all_entries[-1]
113
+ else
114
+ end_entry = all_entries[all_entries.length*0.75]
115
+ end
116
+ end_text = end_entry.single_line_text
117
+ end_srt_time = end_entry.beginning_time
118
+ human_end = EdlParser.translate_time_to_human_readable(end_srt_time)
119
+ end_movie_ts = get_user_input("Enter beginning timestamp within the movie itself for when the subtitle #{end_entry.index_number}\n\"#{end_text}\"\nfirst appears (possibly near #{human_end}).\nYou can find it by searching to near that time in the movie [pgup+pgdown, then arrow keys], find some subtitle, then find where that subtitle is within the .srt file to see where it lies\nrelative to the one you are interested in\nthen seek relative to that to find the one you want.")
120
+ end_movie_time = EdlParser.translate_string_to_seconds end_movie_ts
121
+ else
122
+ start_srt_time = 0
123
+ start_movie_time = 0
124
+ end_srt_time = 3000
125
+ end_movie_time = 3000
126
+ end
127
+
128
+ parsed_profanities, euphemized_synchronized_entries = nil
129
+ with_autoclose_message("parsing srt file...") do
130
+ parsed_profanities, euphemized_synchronized_entries = SubtitleProfanityFinder.edl_output_from_string File.read(srt_filename), {}, add_to_beginning.to_f, add_to_end.to_f, start_srt_time, start_movie_time, end_srt_time, end_movie_time
131
+ end
132
+
133
+ filename = EdlTempFile + '.parsed.txt'
134
+ out = "# add these into your \"mute\" section if you deem them mutable\n" + parsed_profanities
135
+ if end_srt_time != 3000
136
+ out += %!\n\n#Also add these lines at the bottom of the EDL (for later coordination):\n"beginning_subtitle" => ["#{start_text}", "#{start_movie_ts}"],! +
137
+ %!\n"ending_subtitle_entry" => ["#{end_text}", "#{end_movie_ts}"],!
138
+ middle_entry = euphemized_synchronized_entries[euphemized_synchronized_entries.length*0.5]
139
+ show_blocking_message_dialog "You may want to double check if the math worked out.\n\"#{middle_entry.single_line_text}\" (##{middle_entry.index_number})\nshould first appear at #{EdlParser.translate_time_to_human_readable middle_entry.beginning_time}\nIf it's off much you may want to try a different .srt file"
140
+ end
141
+ File.write filename, out
142
+ open_file_to_edit_it filename
143
+ sleep 1 # let it open
144
+
145
+ if show_select_buttons_prompt("Would you like to write out a synchronized, euphemized .srt file [useful if you want to watch the movie with sanitized subtitles later]?") == :yes
146
+ out_file = new_nonexisting_filechooser_and_go("Select filename to write to", File.dirname(srt_filename), File.basename(srt_filename)[0..-5] + ".euphemized.srt")
147
+ write_subs_to_file out_file, euphemized_synchronized_entries
148
+ show_in_explorer out_file
149
+ end
150
+
151
+ end
152
+
153
+ add_text_line 'Create: Advanced View Edited Options'
154
+
155
+ @mplayer_edl_with_subs = new_jbutton( "Watch DVD edited (realtime) (mplayer) (yes subtitles)") do
156
+ watch_dvd_edited_realtime_mplayer true
157
+ end
158
+
159
+ @mplayer_partial = new_jbutton( "Watch DVD edited (realtime) (mplayer) based on timestamp") do
160
+ times = get_start_stop_times_strings
161
+ times.map!{|t| EdlParser.translate_string_to_seconds t}
162
+ start_time = times[0]
163
+ end_time = times[1]
164
+ extra_mplayer_commands = ["-ss #{start_time}", "-endpos #{end_time - start_time}"]
165
+ play_smplayer_edl_non_blocking nil, extra_mplayer_commands, true, false, add_end = 0.0, add_begin = 0.0 # create mode => aggressive
166
+ end
167
+
168
+ new_jbutton("Display mplayer keyboard commands/howto/instructions") do
169
+ show_mplayer_instructions
170
+ end
171
+
172
+ add_text_line "Create: Watch Unedited Options:"
173
+
174
+ @play_smplayer = new_jbutton( "Watch DVD unedited (realtime smplayer)")
175
+ @play_smplayer.tool_tip = <<-EOL
176
+ This will play the DVD unedited within smplayer.
177
+ NB it will default to title 1, so updated your EDL file that matches this DVD with the proper title if this doesn't work for you
178
+ i.e. if it just plays a single preview title or what not, and not the main title, you need to change this value.
179
+ This is useful if you want to just kind of watch the movie to enjoy it, and look for scenes to cut out.
180
+ You can use the built-in OSD (on-screen-display) to see what time frame the questionable scenes are at
181
+ (type "o" to toggle it). However, just realize that the OSD is in 30 fps, and our time stamps are all in 29.97
182
+ fps, so you'll need to convert it (the convert timestamp button) to be able to use it in a file.
183
+ NB That you can get the mplayer keyboard control instructions with the show instructions button.
184
+ EOL
185
+ @play_smplayer.on_clicked {
186
+ play_dvd_smplayer_unedited false
187
+ }
188
+
189
+ add_text_line "Less commonly used Edit options:"
190
+
191
+ new_jbutton("Create new Edit List (for netflix instant or movie file)") do # LODO VIDEO_TS here too?
192
+ names = ['movie file', 'netflix instant']
193
+ dialog = DropDownSelector.new(self, names, "Select type")
194
+ type = dialog.go_selected_value
195
+ extra_options = {}
196
+ if type == 'movie file'
197
+ path = SwingHelpers.new_previously_existing_file_selector_and_go "Select file to create EDL for"
198
+ guess_name = File.basename(path).split('.')[0..-2].join('.') # like yo.something.720p.HDTV.X264-DIMENSION.m4v maybe?
199
+ extra_options['filename'] = File.basename path
200
+ require 'lib/movie_hasher'
201
+ extra_options['movie_hash'] = MovieHasher.compute_hash path
202
+ else
203
+ url = get_user_input "Please input the movies url (like http://www.netflix.com/Movie/Curious-George/70042686 )" #?
204
+ if url =~ /netflix/
205
+ guess_name = url.split('/')[-2]
206
+ else
207
+ show_blocking_message_dialog "non hulu/netflix? please report!"
208
+ type = 'unknown'
209
+ guess_name = url.split('/')[-1]
210
+ end
211
+ extra_options['url'] = url
212
+ end
213
+ english_name = get_user_input "Enter name of movie", guess_name.gsub(/[-._]/, ' ')
214
+ filename = new_nonexisting_filechooser_and_go 'Pick new EDL filename', EdlParser::EDL_DIR + '/..', english_name.gsub(' ', '_') + '.txt'
215
+ display_and_raise "needs .txt extension" unless filename =~ /\.txt$/i
216
+
217
+ output = <<-EOL
218
+ # edl_version_version 1.1, created by sensible cinema v#{VERSION}
219
+ # comments can go be created by placing text after a # on any line, for example this one.
220
+ "name" => "#{english_name}",
221
+
222
+ "source" => "#{type}",
223
+ #{extra_options.map{|k, v| %!\n"#{k}" => "#{v}",\n!}}
224
+ "mutes" => [
225
+ # an example line, uncomment the leading "#" to make it active
226
+ # "0:00:01.0", "0:00:02.0", "profanity", "da..",
227
+ ],
228
+
229
+ "blank_outs" => [
230
+ # an example line, uncomment the leading "#" to make it active
231
+ # "00:03:00.0" , "00:04:00.0", "violence", "of some sort",
232
+ ],
233
+
234
+ "timestamps_relative_to" => ["#{type}"],
235
+ # "not edited out stuff" => "some...",
236
+ # "closing thoughts" => "only ...",
237
+ # "subtitles_to_display_relative_path" => "some_file.srt" # if you want to display some custom subtitles alongside your movie
238
+ EOL
239
+ File.write filename, output
240
+ open_file_to_edit_it filename
241
+ end
242
+
243
+ new_jbutton("Show even more rarely used buttons") do
244
+ child = new_child_window
245
+ child.show_rarely_used_buttons
246
+ end
247
+
248
+ add_text_line 'Options for creating an edited movie file from a local file:'
249
+
250
+ new_jbutton("Show options to help with creating a fully edited movie file") do
251
+ window = new_child_window
252
+ window.add_options_that_use_local_files
253
+ end
254
+
255
+ end
256
+
257
+ def write_subs_to_file out_file, euphemized_synchronized_entries
258
+ File.open(out_file, 'w') do |f|
259
+ euphemized_synchronized_entries.each_with_index{|entry, idx|
260
+ beginning_time = EdlParser.translate_time_to_human_readable(entry.beginning_time).gsub('.',',')
261
+ ending_time = EdlParser.translate_time_to_human_readable(entry.ending_time).gsub('.',',')
262
+ f.puts entry.index_number
263
+ f.puts "#{beginning_time} --> #{ending_time}"
264
+ f.puts entry.text
265
+ f.puts ''
266
+ }
267
+ end
268
+ end
269
+
270
+ def show_rarely_used_buttons
271
+ if we_are_in_developer_mode?
272
+ @reload = new_jbutton("[programmer mode] reload bin/sensible-cinema code") do
273
+ for file in Dir[__DIR__ + '/*.rb']
274
+ p file
275
+ eval(File.read(file), TOPLEVEL_BINDING, file)
276
+ end
277
+ end
278
+ end
279
+
280
+ @open_list = new_jbutton("Open/Edit an arbitrary file (EDL, .srt file, whatever)")
281
+ @open_list.on_clicked {
282
+ filename = new_existing_file_selector_and_select_file("Pick any file to open in editor", EdlParser::EDL_DIR)
283
+ open_file_to_edit_it filename
284
+ }
285
+
286
+ @display_dvd_info = new_jbutton( "Display information about current DVD (ID, timing, etc.)" )
287
+ @display_dvd_info.tool_tip = "This is useful to setup a DVD's 'unique ID' within an EDL for it. \nIf your EDL doesn't have a line like disk_unique_id => \"...\" then you will want to run this to be able to add that line in."
288
+ @display_dvd_info.on_clicked {
289
+ Thread.new {
290
+ out_hashes, title_lengths = get_disk_info
291
+ out_string = out_hashes.map{|name, value| name.inspect + ' => ' + value.inspect + ','}.join("\n") + "\n" + title_lengths.join("\n")
292
+ out_string += %!\n"timestamps_relative_to" => ["dvd_start_offset","29.97"],! # since they're all this way currently
293
+ filename = EdlTempFile + '.disk_info.txt'
294
+ File.write filename, out_string
295
+ open_file_to_edit_it filename
296
+ out_string # for unit tests :) TODO
297
+ }
298
+ }
299
+
300
+ @convert_seconds_to_ts = new_jbutton( "Convert 3600.0 <-> 1:00:00 style timestamps" )
301
+ @convert_seconds_to_ts.on_clicked {
302
+ input = get_user_input("Enter \"from\" timestamp, like 3600 or 1:40:00:", "1:00:00.1 or 3600.1")
303
+ while(input)
304
+ if input =~ /:/
305
+ output = EdlParser.translate_string_to_seconds input
306
+ output = "%.02f" % output # so they know we're not rounding for example 6.10 not 6.1
307
+ else
308
+ output = EdlParser.translate_time_to_human_readable input.to_f, true
309
+ end
310
+ input = show_copy_pastable_string("Converted:", output)
311
+ end
312
+ }
313
+
314
+ @convert_timestamp = new_jbutton( "Convert timestamp from DVD player time to EDL time (30->29.97 fps)" )
315
+ @convert_timestamp.tool_tip=<<-EOL
316
+ Our EDL's assume 29.97 fps (which is what a DVD actually has). Unfortunately most hardware or commercial DVD players
317
+ think that the DVD is 30 fps, which means that if you use them for timestamps for your EDL's,
318
+ you will be slightly off (at the end of a 2 hour film, by 8 seconds). So all your edits will be wrong.
319
+ How to fix: convert your times from "DVD player" time to "EDL accurate" time by using this button.
320
+ This is necessary for all hardware DVD player timestamps, PowerDVD player (software), Windows Media Player (playing a DVD),
321
+ and mplayer's "on screen display" DVD timestamps.
322
+ It is not necessary for smplayer timestamps (or mplayer's "V: 3600" in the command line), which are already 29.97.
323
+ smplayer's on-screen-display (the 'o' key) is accurate (and doesn't suffer from MPEG timestamps resets midway through)
324
+ but is 30 fps, so timestamps would need to be converted.
325
+ Dont use VLC for DVD timestamps at all--it can get up to 30s off! VLC playing back a file is usually pretty accurate to 29.97.
326
+ In general, GUI's like VLC or smplayer are always a tidge off (maybe 0.3s) from the right timestamp, so take that into consideration.
327
+ Mplayers "V: 3600" is usually right on (29.97 fps), however.
328
+ EOL
329
+ @convert_timestamp.on_clicked {
330
+ thirty_fps = get_user_input("Enter your DVD/hardware (30 fps) timestamp, I'll convert it to 29.97 (usable in EDL's):", "1:00:00.1")
331
+ thirty_fps_in_seconds = EdlParser.translate_string_to_seconds thirty_fps
332
+ twenty_nine_seven_fps = ConvertThirtyFps.from_thirty(thirty_fps_in_seconds)
333
+ human_twenty_nine_seven = EdlParser.translate_time_to_human_readable twenty_nine_seven_fps, true
334
+ show_copy_pastable_string("Sensible cinema usable value (29.97 fps) for #{thirty_fps} would be: ", human_twenty_nine_seven)
335
+ }
336
+
337
+ @create_dot_edl = new_jbutton( "Create a side-by-side moviefilename.edl file [XBMC etc.]")
338
+ @create_dot_edl.tool_tip = <<-EOL
339
+ Creates a moviefilename.edl file (corresponding to some moviefilename.some_ext file already existing)
340
+ XBMC/smplayer (smplayer can be used by WMC plugins, etc.) "automagically detect",
341
+ if it exists, and automatically use it .edl to show that file edited played back.
342
+ If you use smplayer, note that you'll need to download the "lord mulder mplayer"
343
+ version (which includes an updated version of mplayer that fixes some bugs in EDL playback)
344
+ EOL
345
+ @create_dot_edl.on_clicked {
346
+ show_blocking_message_dialog "Warning: With XBMC you'll need Eden 11.0 for mutes to work"
347
+ choose_file_and_edl_and_create_sxs_or_play true
348
+ }
349
+ if LocalStorage['have_zoom_button']
350
+ @create_zoomplayer = new_jbutton( "Create a ZoomPlayer MAX compatible EDL file") do
351
+ raise unless OS.doze?
352
+ @prompt ||= show_blocking_message_dialog <<-EOL
353
+ To work with ZoomPlayer MAX's scene cut functionality, first play the DVD you want to watch edited, and
354
+ create a dummy cut for it in it via the ZoomPlayer MAX cut scene editor. (right click -> open interface -> scene cut editor)
355
+ Once you create a cut, ZoomPlayer will create a file like this:
356
+ [windows 7]: c:\\Users\\All Users\\Zoom Player\\DVD-Bookmarks\\Sintel_NTSC.3D4D1DFBEB1A53FE\\disc.cut
357
+
358
+ After it has been created, come back to this. You will next be prompted to select the generated disc.cut file, and also a sensible cinema EDL file.
359
+ The generated file will then be overwritten with the sensible cinema EDL information.
360
+ DVD compatible only currently--ask if you want it for file based selection as well and I can add it.
361
+ EOL
362
+ zoom_path = new_existing_file_selector_and_select_file( "Pick Zoomplayer disc.cut File to override", ENV["ALLUSERSPROFILE"]+ '/Zoom Player/DVD-Bookmarks' )
363
+ edl_path = new_existing_file_selector_and_select_file( "Pick EDL", EdlParser::EDL_DIR)
364
+ specs = parse_edl(edl_path)
365
+ require_relative '../zoom_player_max_edl'
366
+ out = ZoomPlayerMaxEdl.convert_to_edl_string specs
367
+ File.write(zoom_path, out)
368
+ show_blocking_message_dialog "wrote #{zoom_path}"
369
+ end
370
+ end
371
+ end
372
+
373
+ def get_disk_info
374
+ drive, volume_name, dvd_id = choose_dvd_drive_or_file true # require a real DVD disk :)
375
+ # display it, allow them to copy and paste it out
376
+ out_hashes = {}
377
+ out_hashes['disk_unique_id'] = dvd_id
378
+ out_hashes['volume_name'] = volume_name
379
+ popup = show_non_blocking_message_dialog "calculating DVD title sizes..."
380
+ command = "mplayer -vo direct3d dvdnav:// -nocache -dvd-device #{drive} -identify -frames 0 2>&1"
381
+ puts command
382
+ title_lengths_output = `#{command}`
383
+ popup.close
384
+ edit_list_path = EdlParser.single_edit_list_matches_dvd(dvd_id)
385
+ if edit_list_path
386
+ parsed = parse_edl edit_list_path
387
+ title_to_get_offset_of = get_title_track_string(parsed)
388
+ else
389
+ title_to_get_offset_of = nil
390
+ end
391
+ title_lengths = title_lengths_output.split("\n").select{|line| line =~ /TITLE.*LENGTH/}
392
+ # ID_DVD_TITLE_4_LENGTH=365.000
393
+ titles_with_length = title_lengths.map{|name| name =~ /ID_DVD_TITLE_(\d+)_LENGTH=([\d\.]+)/; [$1, $2.to_f]}
394
+ largest_title = titles_with_length.max_by{|title, length| length}
395
+ if !largest_title
396
+ display_and_raise "unable to parse title lengths? maybe need to clean disk first? #{title_lengths_output}"
397
+ end
398
+ largest_title = largest_title[0]
399
+ title_to_get_offset_of ||= largest_title
400
+ out_hashes['dvd_title_track'] = title_to_get_offset_of
401
+ out_hashes['dvd_title_track_length'] = titles_with_length.detect{|title, length| title == title_to_get_offset_of}[1]
402
+ offsets = calculate_dvd_start_offset(title_to_get_offset_of, drive)
403
+ start_offset = offsets[:mpeg_start_offset]
404
+ out_hashes['dvd_start_offset'] = start_offset
405
+ out_hashes['dvd_nav_packet_offset'] = offsets[:dvd_nav_packet_offset]
406
+ [out_hashes, title_lengths]
407
+ end
408
+
409
+ def watch_dvd_edited_realtime_mplayer show_subs
410
+ edl_out_command = ""
411
+ if !@has_ever_rejected_edl_outfile
412
+ answer = show_select_buttons_prompt <<-EOL, {}
413
+ Would you like to create an .edl outfile as it plays (hit button to capture timestamps)?
414
+ EOL
415
+ if answer == :yes
416
+ show_non_blocking_message_dialog <<-EOL
417
+ EDL outfile:
418
+ As mplayer goes through the video, when you see a scene you want to edit or skip,
419
+ hit 'i' and mplayer will write the start time in the file and set it to skip for 2 seconds,
420
+ hit 'i' again to end the edited/skipped scene, within that file.
421
+ EOL
422
+
423
+ edlout_filename = new_nonexisting_filechooser_and_go "pick edlout filename"
424
+ edl_out_command = "-edlout #{edlout_filename}"
425
+
426
+ else
427
+ @has_ever_rejected_edl_outfile = true
428
+ end
429
+ end
430
+ thred = play_smplayer_edl_non_blocking nil, [edl_out_command], true, false, add_end = 0.0, add_begin = 0.0, show_subs # more aggressive :)
431
+ if(edl_out_command.present?)
432
+ open_edl_file_when_done thred, edlout_filename
433
+ end
434
+ end
435
+
436
+ def calculate_dvd_start_offset title, drive
437
+ popup = show_non_blocking_message_dialog "calculating start info for title #{title}..." # must be non blocking so the command can run :P
438
+ command = "mplayer -benchmark -frames 35 -osd-verbose -osdlevel 2 -vo null -nosound dvdnav://#{title} -nocache -dvd-device #{drive} 2>&1"
439
+ puts command
440
+ out = `#{command}`
441
+ #search for V: 0.37
442
+ popup.close
443
+ outs = {}
444
+ old_mpeg = 0
445
+ out.each_line{|l|
446
+ if l =~ /V:\s+([\d\.]+)/
447
+ outs[:mpeg_start_offset] ||= $1.to_f
448
+ end
449
+ float = /\d+\.\d+/
450
+ if l =~ /last NAV packet was (#{float}), mpeg at (#{float})/
451
+ nav = $1.to_f
452
+ mpeg = $2.to_f
453
+ if !outs[:dvd_nav_packet_offset] && nav > 0.0 # like 0.4
454
+ if mpeg < nav
455
+ # case there is an MPEG split before the second NAV packet [ratatouille]
456
+ p mpeg, nav, old_mpeg
457
+ assert old_mpeg > 0.3
458
+ mpeg = old_mpeg + mpeg - 0.033367 # assume 30 fps, and that this is the second frame since it occurred, since the first one we apparently display "weird suddenly we're not a dvd?"
459
+ show_blocking_message_dialog "this dvd has some weird stuff at the start, attempting to accomodate..."
460
+ end
461
+ outs[:dvd_nav_packet_offset] = [nav, mpeg] # like [0.4, 0.6] or the like
462
+ else
463
+ old_mpeg = mpeg # ratatouile weirdness...
464
+ end
465
+ end
466
+ }
467
+ show_blocking_message_dialog "unable to calculate time?" unless outs.length == 2
468
+ outs
469
+ end
470
+
471
+ def get_start_stop_times_strings
472
+ # only show this message once :)
473
+ @show_block ||= show_blocking_message_dialog(<<-EOL, "Preview")
474
+ Ok, let's preview just a portion of it.
475
+ Note that you'll want to preview a section that wholly includes an edit section within it.
476
+ For example, if it mutes from second 1 to second 10, you'll want to play from 00:00 to 00:12 or what not.
477
+ Also note that the first time you preview a section of a video, it will take a long time (like an hour) as it sets up the entire video for processing.
478
+ Subsequent previews will be faster, though, as long as you use the same filename, as it won't have to re-set it up for processing.
479
+ Also note that if you change your edit list, you'll need to close, and restart the video to be able to see it with your new settings.
480
+ EOL
481
+ old_start = LocalStorage['start_time']
482
+ start_time = get_user_input("At what point in the video would you like to start your preview? (like 01:00 for starting at 1 minute)", LocalStorage['start_time'])
483
+ default_end = LocalStorage['end_time']
484
+ if start_time and start_time != old_start
485
+ default_end = EdlParser.translate_string_to_seconds(start_time) + 10
486
+ default_end = EdlParser.translate_time_to_human_readable(default_end)
487
+ end
488
+ end_time = get_user_input("At what point in the video would you like to finish your preview? (like 02:00 for ending at the 2 minute mark)", default_end)
489
+ unless start_time and end_time
490
+ # this one is raw showMessageDialog...
491
+ JOptionPane.showMessageDialog(nil, " Please choose start and end", "Failed", JOptionPane::ERROR_MESSAGE)
492
+ return
493
+ end
494
+ LocalStorage['start_time'] = start_time
495
+ LocalStorage['end_time'] = end_time
496
+ [start_time, end_time]
497
+ end
498
+
499
+ def create_brand_new_dvd_edl
500
+ hashes, title_lengths = get_disk_info # has a prompt
501
+ volume = hashes['volume_name']
502
+ default_english_name = volume.split('_').map{|word| word.downcase.capitalize}.join(' ') # A Court A Jester
503
+ english_name = get_user_input("Enter a human readable DVD description for #{volume}", default_english_name)
504
+
505
+ # EDL versions:
506
+ # nothing with disk_unique_id: probably dvd_start_offset 29.97
507
+ # nothing without disk_unque_id: probably start_zero 29.97
508
+ # 1.1: has timestamps_relative_to, I guess
509
+
510
+ input = <<-EOL
511
+ # edl_version_version 1.1, sensible cinema v#{VERSION}
512
+ # comments can go be created by placing text after a # on any line, for example this one.
513
+ "name" => "#{english_name}",
514
+
515
+ "mutes" => [
516
+ # an example line, uncomment the leading "#" to make it active
517
+ # "0:00:01.0", "0:00:02.0", "profanity", "da..",
518
+ ],
519
+
520
+ "blank_outs" => [
521
+ # an example line, uncomment the leading "#" to make it active
522
+ # "00:03:00.0" , "00:04:00.0", "violence", "of some sort",
523
+ ],
524
+
525
+ "source" => "dvd",
526
+ "volume_name" => "#{volume}",
527
+ "timestamps_relative_to" => ["dvd_start_offset","29.97"],
528
+ "disk_unique_id" => "#{hashes['disk_unique_id']}",
529
+ "dvd_title_track" => "#{hashes['dvd_title_track']}", # our guess for it
530
+ "dvd_title_track_length" => "#{hashes['dvd_title_track_length']}",
531
+ # "not edited out stuff" => "some...",
532
+ # "closing thoughts" => "only ...",
533
+ # "subtitles_to_display_relative_path" => "some_file.srt" # if you want to display some custom subtitles alongside your movie
534
+ "dvd_title_track_start_offset" => "#{hashes['dvd_start_offset']}",
535
+ "dvd_nav_packet_offset" => #{hashes['dvd_nav_packet_offset'].inspect},
536
+ EOL
537
+ filename = EdlParser::EDL_DIR + "/edls_being_edited/" + english_name.gsub(' ', '_') + '.txt'
538
+ filename.downcase!
539
+ if File.exist?(filename)
540
+ show_blocking_message_dialog 'cannot overwrite file in the edit dir that already has same name, opening it instead...'
541
+ else
542
+ File.write(filename, input)
543
+ end
544
+ open_file_to_edit_it filename
545
+ end
546
+
547
+ def show_mplayer_instructions
548
+ show_non_blocking_message_dialog <<-EOL
549
+ About to run mplayer. To control it (or smplayer), you can use these keyboard keys:
550
+ spacebar : pause,
551
+ double clicky/right click/'f' : toggle full screen,
552
+ enter : select DVD menu currently highlighted
553
+ arrow keys (left, right, up down, pg up, pg dn) : seek/scan
554
+ / and * : inc/dec volume.
555
+ 'o' key: turn on on-screen-display timestamps see wiki "understanding timestamps"
556
+ 'v' key: toggle display of subtitles.
557
+ '.' key: step forward one frame.
558
+ '#' key: change audio language track
559
+ 'j' : change subtitle track/language
560
+ [ and ] make playback faster or slower [like 2x]
561
+ EOL
562
+ end
563
+
564
+ end
565
+ end