sensible-cinema 0.26.0 → 0.26.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitmodules +3 -0
  2. data/README +9 -6
  3. data/TODO +91 -41
  4. data/VERSION +1 -1
  5. data/bin/sensible-cinema +13 -1506
  6. data/bin/sensible-cinema-cli +156 -151
  7. data/change_log_with_feature_list.txt +17 -2
  8. data/developer_how_to_contribute_to_the_project.txt +3 -2
  9. data/documentation/upconversion.txt +4 -0
  10. data/history_and_related_works_list.txt +1 -0
  11. data/{play_with_inserted_scene.bat → legal/play_with_inserted_scene.bat} +0 -0
  12. data/{play_with_overlay.bat → legal/play_with_overlay.bat} +0 -0
  13. data/legal2 +2 -0
  14. data/lib/count_down_timer_jruby_swing.rb +3 -4
  15. data/lib/edl_parser.rb +345 -339
  16. data/lib/eight_three.rb +6 -1
  17. data/lib/gui/sensible-cinema-base.rb +671 -0
  18. data/lib/gui/sensible-cinema-create.rb +304 -0
  19. data/lib/{sensible-cinema-dependencies.rb → gui/sensible-cinema-dependencies.rb} +0 -0
  20. data/lib/gui/sensible-cinema-normal.rb +349 -0
  21. data/lib/gui/sensible-cinema-side-by-side.rb +27 -0
  22. data/lib/gui/sensible-cinema-upconvert.rb +254 -0
  23. data/lib/screen_tracker.rb +1 -0
  24. data/spec/edl_parser.spec.rb +6 -0
  25. data/spec/notes +107 -16
  26. data/spec/sensible_cinema_gui.spec.rb +63 -58
  27. data/todo.inventionzy.txt +12 -0
  28. data/todo.propaganda +1 -2
  29. data/todo.upconvert +3 -1
  30. data/upconvert_netflix/record_screen/record.bat +2 -0
  31. data/upconvert_netflix/record_screen/recording/1.png +0 -0
  32. data/upconvert_netflix/record_screen/recording/10.png +0 -0
  33. data/upconvert_netflix/record_screen/recording/2.png +0 -0
  34. data/upconvert_netflix/record_screen/recording/3.png +0 -0
  35. data/upconvert_netflix/record_screen/recording/4.png +0 -0
  36. data/upconvert_netflix/record_screen/recording/5.png +0 -0
  37. data/upconvert_netflix/record_screen/recording/6.png +0 -0
  38. data/upconvert_netflix/record_screen/recording/7.png +0 -0
  39. data/upconvert_netflix/record_screen/recording/8.png +0 -0
  40. data/upconvert_netflix/record_screen/recording/9.png +0 -0
  41. data/upconvert_netflix/record_screen/recording/d.png +0 -0
  42. data/www/content_editor.html +2 -2
  43. data/zamples/edit_decision_lists/dvds/edls_being_edited/cars_disney.txt +5 -7
  44. data/zamples/edit_decision_lists/dvds/innerspace.txt +77 -0
  45. data/zamples/edit_decision_lists/netflix_instant/avatar-last-air-bender-movie.txt +12 -0
  46. data/zamples/edit_decision_lists/netflix_instant/avatar-last-airbender-series.txt +1 -0
  47. data/zamples/players/netflix/netflix_firefox_non_maximized.txt +1 -1
  48. metadata +28 -11
  49. data/lib/file_chooser.rb +0 -46
  50. data/lib/swing_helpers.rb +0 -142
  51. data/www/monkey.png +0 -0
@@ -0,0 +1,304 @@
1
+ module SensibleSwing
2
+
3
+ class MainWindow
4
+
5
+ def setup_advanced_buttons
6
+
7
+ new_jbutton("Display the standard buttons") do
8
+ window = new_child_window
9
+ window.setup_normal_buttons
10
+ end
11
+
12
+ @mplayer_edl = new_jbutton( "Watch DVD edited (realtime) (mplayer)")
13
+ @mplayer_edl.on_clicked {
14
+ play_mplayer_edl_non_blocking nil, [], true, false
15
+ }
16
+
17
+ add_text_line 'Realtime/Create Options:'
18
+
19
+ @create_new_edl_for_current_dvd = new_jbutton("Create new Edit List for a DVD",
20
+ "If your DVD doesn't have an EDL created for it, this will be your first step--create an EDL file for it.")
21
+ @create_new_edl_for_current_dvd.on_clicked do
22
+ create_brand_new_edl
23
+ @display_dvd_info.simulate_click # for now...
24
+ end
25
+
26
+ @open_list = new_jbutton("Open/Edit a previously created Edit List file", "If your DVD has a previously existing EDL for it, you can open it to edit it with this button.")
27
+ @open_list.on_clicked {
28
+ filename = new_existing_file_selector_and_select_file( "Pick any file to open in editor", EdlParser::EDL_DIR)
29
+ open_file_to_edit_it filename
30
+ }
31
+
32
+ @play_smplayer = new_jbutton( "Watch full DVD unedited (realtime smplayer)")
33
+ @play_smplayer.tool_tip = <<-EOL
34
+ This will play the DVD unedited within smplayer.
35
+ 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
36
+ i.e. if it just plays a single preview title or what not, and not the main title, you need to change this value.
37
+ This is useful if you want to just kind of watch the movie to enjoy it, and look for scenes to cut out.
38
+ You can use the built-in OSD (on-screen-display) to see what time frame the questionable scenes are at
39
+ (type "o" to toggle it). However, just realize that the OSD is in 30 fps, and our time stamps are all in 29.97
40
+ fps, so you'll need to convert it (the convert timestamp button) to be able to use it in a file.
41
+ EOL
42
+ @play_smplayer.on_clicked {
43
+ play_dvd_smplayer_unedited false, true, true
44
+ }
45
+
46
+ @play_mplayer_raw = new_jbutton( "Watch full DVD unedited (realtime mplayer)")
47
+ @play_mplayer_raw.tool_tip = <<-EOL
48
+ This is also useful for comparing subtitle files to see if they have accurate timings.
49
+ If you turn on subtitles (use the v button), then compare your srt file at say, the 1 hour mark, or 2 hour mark,
50
+ with the subtitles that mplayer displays, it *should* match exactly with the output in the command line,
51
+ like "V: 3600.0" should match your subtitle line "01:00:00,000 --> ..."
52
+ EOL
53
+ @play_mplayer_raw.on_clicked {
54
+ play_dvd_smplayer_unedited true, true, true
55
+ }
56
+
57
+ @parse_srt = new_jbutton("Scan a subtitle file (.srt) to detect profanity times automatically" )
58
+ @parse_srt.tool_tip = <<-EOL
59
+ You can download a .srt file and use it to automatically search for profanities.
60
+ Basically download it from opensubtitles.org (possibly from other sites, too),
61
+ (enter dvd name in the search box, click a result, click one from the list with an English flag, then click 'Download(zip)')
62
+ Once you download the zip, unzip it, and then compare the timestamps in it with those on the DVD (see the button "Watch DVD unedited (realtime mplayer)")
63
+ NB that you'll first want/need to *carefully* double check your subtitle
64
+ file with the actual DVD. (ex: smplayer, hit the 'o' button to display
65
+ the current timestamp, then go to the end, stop at some point with text
66
+ and hit the '.' key until a subtitle very first displays.
67
+ Next convert that number to 29.97 fps (using the button given).
68
+ The numbers should match precisely. If they don't, edit this file
69
+ so that it will have some offsets given.
70
+ EOL
71
+
72
+ @parse_srt.on_clicked do
73
+ filename = new_existing_file_selector_and_select_file("Pick srt file to scan for profanity:")
74
+ add_to_beginning = get_user_input("How much time to subtract from the beginning of each subtitle entry (ex: 1:00 -> 1:01 becomes 0:59 -> 1:01)", "0.0")
75
+ add_to_end = get_user_input("How much time to add to the end of each subtitle entry (ex: 1:00 -> 1:01 becomes 1:00 -> 1:02)", "0.0")
76
+ parsed = SubtitleProfanityFinder.edl_output filename, {}, add_to_beginning.to_f, add_to_end.to_f # flight: TODO necessary typically ??? 0.35, 0.25
77
+ File.write(EdlTempFile, "# add these into your mute section if you deem them mute-worthy\n" + parsed)
78
+ open_file_to_edit_it filename, true
79
+ sleep 0.3 if OS.mac? # add delay...
80
+ open_file_to_edit_it EdlTempFile
81
+ end
82
+
83
+ @display_dvd_info = new_jbutton( "Display information about current DVD (ID, etc.)" )
84
+ @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."
85
+ @display_dvd_info.on_clicked {
86
+ drive, volume_name, dvd_id = choose_dvd_drive_or_file true # real DVD disk
87
+ # display it, allow them to copy and paste it out
88
+ title_lengths = nil
89
+ t = Thread.new { title_lengths= `mplayer dvdnav:// -nocache -dvd-device #{drive} -identify -frames 0 2>&1| grep LENGTH` }
90
+ id_string = "\"disk_unique_id\" => \"#{dvd_id}\", # #{volume_name}"
91
+ show_copy_pastable_string "#{drive} #{volume_name} for your copying+pasting pleasure (highlight, then ctrl+c to copy)\n
92
+ This is USED eventually to identify a disk to match it to its EDL, later.", id_string
93
+ t.join
94
+ File.write EdlTempFile, id_string + "\n" + title_lengths
95
+ open_file_to_edit_it EdlTempFile
96
+ id_string
97
+ }
98
+
99
+ @convert_seconds_to_ts = new_jbutton( "Convert 3600 <-> 1:00:00 style timestamps" )
100
+ @convert_seconds_to_ts.on_clicked {
101
+ input = get_user_input("Enter \"from\" timestamps, like 3600 or 1:40:00:", "1:00:00.1 or 3600.1")
102
+ while(input)
103
+ if input =~ /:/
104
+ output = EdlParser.translate_string_to_seconds input
105
+ else
106
+ output = EdlParser.translate_time_to_human_readable input.to_f, true
107
+ end
108
+ input = show_copy_pastable_string("Converted:", output)
109
+ end
110
+ }
111
+
112
+ @convert_timestamp = new_jbutton( "Convert timestamp from DVD player time to EDL time (30->29.97 fps)" )
113
+ @convert_timestamp.tool_tip=<<-EOL
114
+ Our EDL's assume 29.97 fps (which is what a DVD actually has). Unfortunately most hardware or commercial DVD players
115
+ think that the DVD is 30 fps, which means that if you use them for timestamps for your EDL's,
116
+ you will be slightly off (at the end of a 2 hour film, by 8 seconds). So all your edits will be wrong.
117
+ How to fix: convert your times from "DVD player" time to "EDL accurate" time by using this button.
118
+ This is necessary for all hardware DVD player timestamps, PowerDVD player (software), Windows Media Player (playing a DVD),
119
+ and mplayer's "on screen display" DVD timestamps.
120
+ It is not necessary for smplayer timestamps (or mplayer's "V: 3600" in the command line), which are already 29.97.
121
+ smplayer's on-screen-display (the 'o' key) is accurate (and doesn't suffer from dvd_mplayer_splits)
122
+ but is 30 fps, so timestamps would need to be converted.
123
+ 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.
124
+ 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.
125
+ Mplayers "V: 3600" is usually right on (29.97 fps), however.
126
+ EOL
127
+ @convert_timestamp.on_clicked {
128
+ thirty_fps = get_user_input("Enter your DVD (30 fps) timestamp, I'll convert it to 29.97 (usable in EDL's):", "1:00:00.1")
129
+ thirty_fps_in_seconds = EdlParser.translate_string_to_seconds thirty_fps
130
+ twenty_nine_seven_fps = ConvertThirtyFps.from_thirty(thirty_fps_in_seconds)
131
+ human_twenty_nine_seven = EdlParser.translate_time_to_human_readable twenty_nine_seven_fps, true
132
+ show_copy_pastable_string("Sensible cinema usable value (29.97 fps) for #{thirty_fps} would be: ", human_twenty_nine_seven)
133
+ }
134
+
135
+ @create_dot_edl = new_jbutton( "Create a side-by-side moviefilename.edl file")
136
+ @create_dot_edl.tool_tip = <<-EOL
137
+ Creates a moviefilename.edl file (corresponding to some moviefilename.some_ext file already existing)
138
+ XBMC/smplayer (smplayer can be used by WMC plugins, etc.) "automagically detect",
139
+ if it exists, and automatically use it .edl to show that file edited played back.
140
+ If you use smplayer, note that you'll need to download the "lord mulder mplayer"
141
+ version (which includes an updated version of mplayer that fixes some bugs in EDL playback)
142
+ EOL
143
+ @create_dot_edl.on_clicked {
144
+ choose_file_and_edl_and_create_sxs_or_play true
145
+ }
146
+
147
+ add_text_line 'Create Options with local intermediary file:'
148
+
149
+ new_jbutton("Show options with local intermediary file") do
150
+ window = new_child_window
151
+ window.add_options_that_use_local_files
152
+ end
153
+
154
+ # @reload = new_jbutton("reload bin/sensible-cinema code") do
155
+ # load $0
156
+ # end
157
+
158
+ end # advanced buttons
159
+
160
+ def add_options_that_use_local_files
161
+ add_text_line 'Create Options that first create/use a local intermediary file:'
162
+
163
+ @preview_section = new_jbutton( "Preview a certain time frame from fulli file (edited)" )
164
+ @preview_section.tool_tip = <<-EOL
165
+ This allows you to preview an edit easily.
166
+ It is the equivalent of saying \"watch this file edited from exactly minute x second y to minute z second q"
167
+ 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.
168
+ EOL
169
+ @preview_section.on_clicked {
170
+ do_create_edited_copy_via_file true
171
+ }
172
+
173
+ @preview_section_unedited = new_jbutton("Preview a certain time frame from fulli file (unedited)" )
174
+ @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."
175
+ @preview_section_unedited.on_clicked {
176
+ do_create_edited_copy_via_file true, false, true
177
+ }
178
+
179
+ @rerun_preview = new_jbutton( "Re-run most recently watched preview time frame from fulli file" )
180
+ @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."
181
+ @rerun_preview.on_clicked {
182
+ repeat_last_copy_dvd_to_hard_drive
183
+ }
184
+
185
+ # Maybe this button should go too...
186
+ @fast_preview = new_jbutton("fast preview all from fulli file (smplayer EDL)")
187
+ @fast_preview.tool_tip = <<-EOL
188
+ Plays smplayer on a file with an EDL.
189
+ This gives you a rough estimate to see if your edits are accurate, and is really fast to seek, etc.
190
+ This is useful because you can't use mplayer on a DVD for accurate timestamps if it has any
191
+ timestamp splits in it [because some DVD's are buggy]
192
+ EOL
193
+ @fast_preview.on_clicked {
194
+ success, wrote_to_here_fulli = do_create_edited_copy_via_file false, true
195
+ sleep 0.5 # lodo take out ???
196
+ background_thread.join if background_thread # let it write out the original fulli, if necessary [?]
197
+ nice_file = wrote_to_here_fulli
198
+ run_smplayer_blocking nice_file, nil, "-edl #{normalize_path EdlTempFile}", false, true, false
199
+ }
200
+ end
201
+
202
+ def do_create_edited_copy_via_file should_prompt_for_start_and_end_times, exit_early_if_fulli_exists = false, watch_unedited = false
203
+ drive_or_file, dvd_volume_name, dvd_id, edit_list_path, descriptors = choose_dvd_or_file_and_edl_for_it
204
+
205
+ descriptors = parse_edl(edit_list_path)
206
+ if watch_unedited
207
+ # reset them
208
+ descriptors['mutes'] = descriptors['blank_outs'] = []
209
+ end
210
+
211
+ # LODO allow for spaces in the save_to filename
212
+ if should_prompt_for_start_and_end_times
213
+ # only show this message once :)
214
+ @show_block ||= show_blocking_message_dialog(<<-EOL, "Preview")
215
+ Ok, let's preview just a portion of it.
216
+ Note that you'll want to preview a section that wholly includes a deleted section in it.
217
+ 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.
218
+ 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.
219
+ 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.
220
+ 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.
221
+ EOL
222
+ old_start = LocalStorage['start_time']
223
+ 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'])
224
+ default_end = LocalStorage['end_time']
225
+ if start_time and start_time != old_start
226
+ default_end = EdlParser.translate_string_to_seconds(start_time) + 10
227
+ default_end = EdlParser.translate_time_to_human_readable(default_end)
228
+ end
229
+ 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)
230
+ unless start_time and end_time
231
+ # this one is raw showMessageDialog...
232
+ JOptionPane.showMessageDialog(nil, " Please choose start and end", "Failed", JOptionPane::ERROR_MESSAGE)
233
+ return
234
+ end
235
+ LocalStorage['start_time'] = start_time
236
+ LocalStorage['end_time'] = end_time
237
+ end
238
+ dvd_friendly_name = descriptors['name']
239
+ unless dvd_friendly_name
240
+ drive_or_file, dvd_volume_name, dvd_id, edit_list_path, descriptors = choose_dvd_or_file_and_edl_for_it
241
+ descriptors = parse_edl(edit_list_path)
242
+ raise 'no dvd name in EDL?' + edit_list_path + File.read(edit_list_path)
243
+ end
244
+
245
+ dvd_title_track = get_title_track(descriptors)
246
+ if dvd_id == NonDvd
247
+ file_from = drive_or_file
248
+ else
249
+ file_from = get_grabbed_equivalent_filename_once dvd_friendly_name, dvd_title_track # we don't even care about the drive letter anymore...
250
+ end
251
+ show_blocking_message_dialog("warning: file #{file_from} is not a .mpg or .ts file--it may not work properly all the way--if it's mkv and fails consider first converting to ts by using tsmuxer.") unless file_from =~ /\.(ts|mpg|mpeg)$/i
252
+ save_to_edited = get_save_to_filename dvd_friendly_name
253
+ fulli = MencoderWrapper.calculate_fulli_filename save_to_edited
254
+ if exit_early_if_fulli_exists
255
+ if fulli_dot_done_file_exists? save_to_edited
256
+ return [true, fulli]
257
+ end
258
+ # make it create a dummy response file for us :)
259
+ start_time = "00:00"
260
+ end_time = "00:01"
261
+ end
262
+ should_run_mplayer = should_prompt_for_start_and_end_times || exit_early_if_fulli_exists
263
+ require_deletion_entry = true unless watch_unedited
264
+ 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, require_deletion_entry
265
+ [false, fulli] # false means it's running in a background thread :P
266
+ end
267
+
268
+ def create_brand_new_edl
269
+ drive, volume, dvd_id = choose_dvd_drive_or_file true
270
+ english_name = get_user_input("Enter a human readable DVD description for #{volume}", volume.gsub('_', ' ').downcase)
271
+ input = <<-EOL
272
+ # comments can go after a # on any line, for example this one.
273
+ "name" => "#{english_name}",
274
+
275
+ "mutes" => [
276
+ # an example line, uncomment the leading "#" to make it active
277
+ # "0:00:01.0", "0:00:02.0", "profanity", "da..",
278
+ ],
279
+
280
+ "blank_outs" => [
281
+ # an example line, uncomment the leading "#" to make it active
282
+ # "00:03:00.0" , "00:04:00.0", "violence", "of some sort",
283
+ ],
284
+
285
+ "volume_name" => "#{volume}",
286
+ "disk_unique_id" => "#{dvd_id}",
287
+ "dvd_title_track" => "1", # the "show DVD info" button will tell you title lengths (typically longest title is the title track)
288
+ # "dvd_title_track_length" => "9999", # length, on the DVD, of dvd_title_track (use the show DVD info button to get this number).
289
+ # "subtitle_url" => "1234567",
290
+ # "not edited out stuff" => "some...",
291
+ # "closing thoughts" => "only...",
292
+ # In mplayer, the DVD timestamp "resets" to zero for some reason, so you need to specify when if you want to use mplayer DVD realtime playback, or use mencoder -edl to split your file. See http://goo.gl/yMfqX
293
+ # "mplayer_dvd_splits" => ["59:59", "1:04:59"], # or [] if there are none. Additive currently. 12345.6 ok.
294
+ EOL
295
+ # TODO auto-ify above, move docs to a file in documentation.
296
+ filename = EdlParser::EDL_DIR + "/edls_being_edited/" + english_name.gsub(' ', '_') + '.txt'
297
+ filename.downcase!
298
+ File.write(filename, input) unless File.exist?(filename) # lodo let them choose name (?)
299
+ open_file_to_edit_it filename
300
+ end
301
+
302
+
303
+ end
304
+ end
@@ -0,0 +1,349 @@
1
+ #!/usr/bin/ruby # so my editor will like the file...
2
+ =begin
3
+ Copyright 2010, Roger Pack
4
+ This file is part of Sensible Cinema.
5
+
6
+ Sensible Cinema is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ Sensible Cinema is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
18
+ =end
19
+
20
+ module SensibleSwing
21
+
22
+ class MainWindow < JFrame
23
+
24
+ attr_accessor :parent, :upconv_line
25
+
26
+
27
+ # converts to full path, 8.3 if on doze
28
+ def normalize_path path
29
+ path = File.expand_path path
30
+ path = EightThree.convert_path_to_8_3 path if OS.doze?
31
+ end
32
+
33
+ def setup_normal_buttons
34
+ add_text_line ""
35
+
36
+ @mplayer_edl = new_jbutton( "Watch DVD edited (realtime)")
37
+ @mplayer_edl.tool_tip = "This will watch your DVD in realtime from your computer while skipping/muting questionable scenes."
38
+ @mplayer_edl.on_clicked {
39
+ play_mplayer_edl_non_blocking
40
+ }
41
+
42
+ @create = new_jbutton( "Create edited copy of DVD/file on Your Hard Drive" )
43
+ @create.tool_tip = <<-EOL
44
+ This takes a file and creates a new file on your hard disk like dvd_name_edited.mpg that you can watch when it's done.
45
+ The file you create will contain the whole movie edited.
46
+ It takes quite awhile maybe 2 hours. Sometimes the progress bar will look paused--it typically continues eventually.
47
+ EOL
48
+ @create.on_clicked {
49
+ do_create_edited_copy_via_file false
50
+ }
51
+
52
+ @watch_file_edl = new_jbutton( "Watch movie file edited (realtime)" ) do
53
+ choose_file_and_edl_and_create_sxs_or_play false
54
+ end
55
+
56
+ if LocalStorage[UpConvertEnglish]
57
+ add_text_line ''
58
+ add_open_documentation_button
59
+ @upconv_line = add_text_line " #{get_current_upconvert_as_phrase}"
60
+ else
61
+ @upconv_line = add_text_line ''
62
+ add_open_documentation_button
63
+ end
64
+
65
+ add_change_upconvert_options_button
66
+
67
+ @progress_bar = JProgressBar.new(0, 100)
68
+ @progress_bar.set_bounds(44,@starting_button_y,@button_width,23)
69
+ @progress_bar.visible = false
70
+ @panel.add @progress_bar
71
+
72
+ end
73
+
74
+ def add_open_documentation_button
75
+ @open_help_file = new_jbutton("View Sensible Cinema Documentation") do
76
+ show_in_explorer __DIR__ + "/../documentation" # TODO mac :)
77
+ end
78
+ end
79
+
80
+ def choose_file_and_edl_and_create_sxs_or_play just_create_dot_edl_file_instead_of_play
81
+ filename_mpg = new_existing_file_selector_and_select_file( "Pick moviefile (like moviename.mpg or video_ts/anything.ext)")
82
+ edl_filename = new_existing_file_selector_and_select_file( "Pick an EDL file to use with it", EdlParser::EDL_DIR)
83
+ assert_ownership_dialog
84
+ if just_create_dot_edl_file_instead_of_play
85
+ descriptors = EdlParser.parse_file edl_filename
86
+ # LODO these timings...DRY up...plus is XBMC the same? what about on a slower computer?
87
+ # NB these are just for the Side by side EDL's!
88
+
89
+ edl_contents = MplayerEdl.convert_to_edl descriptors, add_secs_end = MplayerEndBuffer, MplayerBeginingBuffer, splits = []
90
+ output_file = filename_mpg.gsub(/\.[^\.]+$/, '') + '.edl' # sanitize...
91
+ File.write(output_file, edl_contents)
92
+ raise unless File.exist?(output_file)
93
+ show_blocking_message_dialog("created #{output_file}")
94
+ else
95
+ play_mplayer_edl_non_blocking [filename_mpg, edl_filename]
96
+ end
97
+ end
98
+
99
+ def we_are_in_upconvert_mode
100
+ ARGV.index("--upconvert-mode")
101
+ end
102
+
103
+ def setup_default_buttons
104
+ if we_are_in_upconvert_mode
105
+ add_play_upconvert_buttons
106
+ else
107
+
108
+ if we_are_in_create_mode
109
+ setup_advanced_buttons
110
+ add_text_line 'Contact:'
111
+ else
112
+ setup_normal_buttons
113
+ end
114
+
115
+ @upload = new_jbutton("Submit Feedback/Upload new EDL's/Request Help") # keeps this one last! :)
116
+ @upload.tool_tip = "We welcome all feedback!\nQuestion, comments, request help.\nAlso if you create a new EDL, please submit it back to us so that others can benefit from it later!"
117
+ @upload.on_clicked {
118
+ system_non_blocking("start mailto:sensible-cinema@googlegroups.com")
119
+ system_non_blocking("start http://groups.google.com/group/sensible-cinema")
120
+ }
121
+ increment_button_location
122
+
123
+ end
124
+
125
+ @exit = new_jbutton("Exit", "Exits the application and kills any background processes that are running at all--don't exit unless you are done processing all the way!")
126
+ @exit.on_clicked {
127
+ Thread.new { self.close } # don't waste the time to close it :P
128
+ puts 'Thank you for using Sensible Cinema. Come again!'
129
+ System.exit 0
130
+ }
131
+
132
+ increment_button_location
133
+ increment_button_location
134
+ self
135
+
136
+ end
137
+
138
+ def repeat_last_copy_dvd_to_hard_drive
139
+ generate_and_run_bat_file *LocalStorage['last_params']
140
+ end
141
+
142
+ def parse_edl path
143
+ EdlParser.parse_file path
144
+ end
145
+ def get_freespace path
146
+ JFile.new(File.dirname(path)).get_usable_space
147
+ end
148
+
149
+
150
+ def get_title_track descriptors, use_default_of_one = true
151
+ given = descriptors["dvd_title_track"]
152
+ given ||= "1" if use_default_of_one
153
+ given
154
+ end
155
+
156
+ def get_grabbed_equivalent_filename_once dvd_title, dvd_title_track
157
+ @_get_grabbed_equivalent_filename_once ||=
158
+ begin
159
+ 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)"
160
+ end
161
+ end
162
+
163
+ def get_save_to_filename dvd_title
164
+ @_get_save_to_filename ||=
165
+ begin
166
+ save_to_file_name = dvd_title + ' edited version'
167
+ save_to_file_name = save_to_file_name.gsub(' ', '_').gsub( /\W/, '') + ".avi" # no punctuation or spaces for now, to not complicate...
168
+ 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
169
+ raise 'no spaces allowed yet' if save_to =~ / /
170
+ begin
171
+ a = File.open(File.dirname(save_to) + "/test_file_to_see_if_we_have_permission_to_write_to_this_folder", "w")
172
+ a.close
173
+ File.delete a.path
174
+ rescue Errno::EACCES => e
175
+ show_blocking_message_dialog "unable to write to that directory, please pick again: " + e.to_s
176
+ raise 'pick again!'
177
+ end
178
+ freespace = get_freespace(save_to)
179
+ if freespace < 8_000_000_000
180
+ show_blocking_message_dialog("Warning: there may not be enough space on the disk for #{save_to}
181
+ (depending on DVD size, you may need around 10G free--you have #{freespace/1_000_000_000}GB free). Click OK to continue.")
182
+ end
183
+ save_to.gsub(/\.avi$/, '')
184
+ end
185
+ end
186
+
187
+
188
+ def get_drive_with_most_space_with_slash
189
+ DriveInfo.get_drive_with_most_space_with_slash
190
+ end
191
+
192
+ def fulli_dot_done_file_exists? save_to_edited
193
+ fulli = MencoderWrapper.calculate_fulli_filename save_to_edited
194
+ File.exist?(fulli + ".done") # stinky!
195
+ end
196
+
197
+ # to make it stubbable :)
198
+ def get_mencoder_commands descriptors, file_from, save_to, start_time, end_time, dvd_title_track, require_deletion_entry
199
+ delete_partials = true unless start_time # in case anybody wants to look really really close [?]
200
+ MencoderWrapper.get_bat_commands descriptors, file_from, save_to, start_time, end_time, dvd_title_track, delete_partials, require_deletion_entry
201
+ end
202
+
203
+ 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
204
+ 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]
205
+ begin
206
+ commands = get_mencoder_commands descriptors, file_from, save_to, start_time, end_time, dvd_title_track, require_deletion_entry
207
+ rescue MencoderWrapper::TimingError => e
208
+ show_blocking_message_dialog("Appears you chose a time frame with no deletion segment in it--please try again:" + e)
209
+ return
210
+ rescue Errno::EACCES => e
211
+ show_blocking_message_dialog("Appears a file on the system is locked: perhaps you need to close down some instance of mplayer?" + e)
212
+ return
213
+ end
214
+ temp_dir = Dir.tmpdir
215
+ temp_file = temp_dir + '/vlc.temp.bat'
216
+ File.write(temp_file, commands)
217
+ popup_message = <<-EOL
218
+ Applying #{File.basename edit_list_path}
219
+ to #{file_from} (#{dvd_title}).
220
+ Copying to #{save_to}.
221
+ EOL
222
+ if !fulli_dot_done_file_exists?(save_to)
223
+ popup_message += "This could take quite awhile (several hours), and will prompt you with a chime noise when it is done.\n
224
+ You can close this window and minimize sensible cinema and continue using your computer while it runs in the background.\n"
225
+ end
226
+
227
+ if !start_time
228
+ # assume a full run..
229
+ popup_message += <<-EOL
230
+ NB that the created file will be playable only with VLC (possibly also with smplayer),
231
+ but probably not with windows media player.
232
+ EOL
233
+ end
234
+
235
+ popup = show_non_blocking_message_dialog(popup_message, "OK")
236
+
237
+ # allow our popups to still be serviced while it is running
238
+ @background_thread = Thread.new { run_batch_file_commands_and_use_output_somehow commands, save_to, file_from, run_mplayer }
239
+ when_thread_done(@background_thread) { popup.dispose }
240
+ # LODO warn if they will overwrite a file in the end...
241
+ end
242
+
243
+ attr_accessor :background_thread, :buttons
244
+
245
+ def run_batch_file_commands_and_use_output_somehow batch_commands, save_to, file_from, run_mplayer_after_done
246
+ @buttons.each{|b| b.set_enabled false}
247
+ success = true
248
+ lines = batch_commands.lines.to_a
249
+ total_size = lines.length.to_f
250
+ @progress_bar.visible=true
251
+ @progress_bar.set_value(10) # start at 10% always, so they can see something.
252
+ lines.each_with_index{|line, idx|
253
+ if success
254
+ puts "running #{line}"
255
+ success = system_blocking(line, true)
256
+ if !success
257
+ puts "\n", 'line failed: ' + line + "\n" + ' see troubleshooting section in README.txt file! ignoring further processing commands...'
258
+ end
259
+ end
260
+ @progress_bar.set_value(10 + idx/total_size*90)
261
+ }
262
+ @progress_bar.visible=false
263
+ @buttons.each{|b| b.set_enabled true}
264
+ if success
265
+ saved_to = save_to + '.avi'
266
+ if run_mplayer_after_done
267
+ run_smplayer_non_blocking saved_to, nil, '', false, false, true
268
+ else
269
+ if File.exist?(saved_to) && (File.size(saved_to).to_f/File.size(file_from) < 0.5) # less than 50% size is suspicious...indeed...check if exists for unit tests.
270
+ show_blocking_message_dialog("Warning: file size differs by more than 50%--it's possible that transcoding failed somehow")
271
+ end
272
+ show_in_explorer saved_to
273
+ PlayAudio.play(File.expand_path(File.dirname(__FILE__)) + "/../vendor/music.wav")
274
+ msg = "Done--you may now watch file\n #{saved_to}\n in VLC player (or possibly smplayer)"
275
+ puts msg # for being able to tell it's done on the command line
276
+ show_blocking_message_dialog msg
277
+ show_in_explorer saved_to # and again, just for kicks [?]
278
+ end
279
+ else
280
+ SwingHelpers.show_blocking_message_dialog "Failed--please examine console output and report back!\nAlso consult the documentation/troubleshooting file.", "Failed", JOptionPane::ERROR_MESSAGE
281
+ end
282
+ end
283
+
284
+ NonDvd = 'non dvd has no dvdid' # we need it for convenience, say you want to go through your indexed vids and convert them all?
285
+
286
+ # returns e:\, volume_name, dvd_id
287
+ # or full_path.mkv, filename, ''
288
+ def choose_dvd_drive_or_file force_choose_only_dvd_drive
289
+ opticals = DriveInfo.get_dvd_drives_as_openstruct
290
+ if @saved_opticals == opticals && @_choose_dvd_drive_or_file
291
+ # memoize...if disks haven't changed :)
292
+ return @_choose_dvd_drive_or_file
293
+ else
294
+ @saved_opticals = opticals # save currently mounted disk list, so we know if we should re-select later...
295
+ # is this ok for os x?
296
+ end
297
+
298
+ has_at_least_one_dvd_inserted = opticals.find{|d| d.VolumeName }
299
+ if !has_at_least_one_dvd_inserted && force_choose_only_dvd_drive
300
+ show_blocking_message_dialog 'insert a dvd first'
301
+ raise 'no dvd found'
302
+ end
303
+ names = opticals.map{|d| d.Name + "\\" + " (" + (d.VolumeName || 'Insert DVD to use') + ")"}
304
+ if !force_choose_only_dvd_drive && !has_at_least_one_dvd_inserted
305
+ names += ['No DVD mounted so choose Local File (or insert DVD, re-try)'] # LODO cannot read it...
306
+ used_local_file_option = true
307
+ end
308
+
309
+ count = 0
310
+ opticals.each{|d| count += 1 if d.VolumeName}
311
+ if count == 1 && !used_local_file_option
312
+ # just choose it if there's only one disk available..
313
+ p 'selecting only disk present in the various DVD drives'
314
+ selected_idx = opticals.index{|d| d.VolumeName}
315
+ unless selected_idx
316
+ show_blocking_message_dialog "Please insert a disk first"
317
+ raise 'inset disk'
318
+ end
319
+
320
+ else
321
+ dialog = get_disk_chooser_window names
322
+ dialog.setSize 200, 125
323
+ dialog.show
324
+ selected_idx = dialog.selected_idx
325
+ end
326
+
327
+ if selected_idx
328
+ if used_local_file_option
329
+ raise unless selected_idx == 0 # it was our only option...
330
+ filename = new_existing_file_selector_and_select_file("Select yer previously grabbed from DVD file")
331
+ assert_ownership_dialog
332
+ return [filename, File.basename(filename), NonDvd]
333
+ else
334
+ disk = opticals[selected_idx]
335
+ out = show_non_blocking_message_dialog "calculating current disk's unique id...if this pauses more than 10s then clean your DVD..."
336
+ dvd_id = DriveInfo.md5sum_disk(disk.MountPoint)
337
+ out.dispose
338
+ @_choose_dvd_drive_or_file = [disk.MountPoint, opticals[selected_idx].VolumeName, dvd_id]
339
+ return @_choose_dvd_drive_or_file
340
+ end
341
+ else
342
+ raise 'did not select a drive...'
343
+ end
344
+ end
345
+
346
+
347
+ end
348
+ end
349
+