sensible-cinema 0.26.0 → 0.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitmodules +3 -0
- data/README +9 -6
- data/TODO +91 -41
- data/VERSION +1 -1
- data/bin/sensible-cinema +13 -1506
- data/bin/sensible-cinema-cli +156 -151
- data/change_log_with_feature_list.txt +17 -2
- data/developer_how_to_contribute_to_the_project.txt +3 -2
- data/documentation/upconversion.txt +4 -0
- data/history_and_related_works_list.txt +1 -0
- data/{play_with_inserted_scene.bat → legal/play_with_inserted_scene.bat} +0 -0
- data/{play_with_overlay.bat → legal/play_with_overlay.bat} +0 -0
- data/legal2 +2 -0
- data/lib/count_down_timer_jruby_swing.rb +3 -4
- data/lib/edl_parser.rb +345 -339
- data/lib/eight_three.rb +6 -1
- data/lib/gui/sensible-cinema-base.rb +671 -0
- data/lib/gui/sensible-cinema-create.rb +304 -0
- data/lib/{sensible-cinema-dependencies.rb → gui/sensible-cinema-dependencies.rb} +0 -0
- data/lib/gui/sensible-cinema-normal.rb +349 -0
- data/lib/gui/sensible-cinema-side-by-side.rb +27 -0
- data/lib/gui/sensible-cinema-upconvert.rb +254 -0
- data/lib/screen_tracker.rb +1 -0
- data/spec/edl_parser.spec.rb +6 -0
- data/spec/notes +107 -16
- data/spec/sensible_cinema_gui.spec.rb +63 -58
- data/todo.inventionzy.txt +12 -0
- data/todo.propaganda +1 -2
- data/todo.upconvert +3 -1
- data/upconvert_netflix/record_screen/record.bat +2 -0
- data/upconvert_netflix/record_screen/recording/1.png +0 -0
- data/upconvert_netflix/record_screen/recording/10.png +0 -0
- data/upconvert_netflix/record_screen/recording/2.png +0 -0
- data/upconvert_netflix/record_screen/recording/3.png +0 -0
- data/upconvert_netflix/record_screen/recording/4.png +0 -0
- data/upconvert_netflix/record_screen/recording/5.png +0 -0
- data/upconvert_netflix/record_screen/recording/6.png +0 -0
- data/upconvert_netflix/record_screen/recording/7.png +0 -0
- data/upconvert_netflix/record_screen/recording/8.png +0 -0
- data/upconvert_netflix/record_screen/recording/9.png +0 -0
- data/upconvert_netflix/record_screen/recording/d.png +0 -0
- data/www/content_editor.html +2 -2
- data/zamples/edit_decision_lists/dvds/edls_being_edited/cars_disney.txt +5 -7
- data/zamples/edit_decision_lists/dvds/innerspace.txt +77 -0
- data/zamples/edit_decision_lists/netflix_instant/avatar-last-air-bender-movie.txt +12 -0
- data/zamples/edit_decision_lists/netflix_instant/avatar-last-airbender-series.txt +1 -0
- data/zamples/players/netflix/netflix_firefox_non_maximized.txt +1 -1
- metadata +28 -11
- data/lib/file_chooser.rb +0 -46
- data/lib/swing_helpers.rb +0 -142
- 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
|
File without changes
|
@@ -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
|
+
|