sensible-cinema 0.18.1 → 0.18.2
Sign up to get free protection for your applications and to get access to all the features.
- data/TODO +3 -8
- data/VERSION +1 -1
- data/bin/sensible-cinema +45 -12
- data/lib/mencoder_wrapper.rb +6 -1
- data/lib/mplayer_edl.rb +8 -10
- data/lib/vlc_programmer.rb +3 -1
- data/sensible-cinema.gemspec +1 -1
- data/spec/mplayer_edl.spec.rb +9 -0
- data/spec/sensible_cinema_gui.spec.rb +29 -18
- data/zamples/edit_decision_lists/dvds/bob the builder pets in a pickle.txt +4 -3
- metadata +2 -2
data/TODO
CHANGED
@@ -2,11 +2,6 @@
|
|
2
2
|
|
3
3
|
== up next release ==
|
4
4
|
|
5
|
-
realtime
|
6
|
-
mplayer EDL...
|
7
|
-
test...
|
8
|
-
out of order ok?
|
9
|
-
|
10
5
|
simplify/de-bugify
|
11
6
|
|
12
7
|
that button shows up? (issue 10)
|
@@ -15,7 +10,8 @@
|
|
15
10
|
re-run latest preview -> auto play in smplayer
|
16
11
|
move that one button *out* ...
|
17
12
|
only pick a drive once per session
|
18
|
-
|
13
|
+
only pick output filename once per session...
|
14
|
+
kill mencoder instances.
|
19
15
|
|
20
16
|
calculating disk's unique id...
|
21
17
|
F:\, Roger's Wedding, a2e3ece630251e4a785218ce71a20ce1
|
@@ -30,7 +26,6 @@ D:\dev\sensible-cinema-never-commit-from-here\zamples\edit_decision_lists\dvds/p
|
|
30
26
|
assert that at least one drive has a DVD in it...maybe loop refuse with message until this?
|
31
27
|
disallow choosing empty drive? fail cleaner? (issue 11)
|
32
28
|
|
33
|
-
|
34
29
|
== slightly lower than that, somewhat ordered ==
|
35
30
|
|
36
31
|
compare computer DVD timings with physical player...
|
@@ -53,6 +48,7 @@ D:\dev\sensible-cinema-never-commit-from-here\zamples\edit_decision_lists\dvds/p
|
|
53
48
|
|
54
49
|
== DVD backlog (unordered, some very low prio, basically never do) ==
|
55
50
|
|
51
|
+
fix some specz
|
56
52
|
can pull from imdb at package time [?]
|
57
53
|
delete fulli file
|
58
54
|
except if it's a specific scene run...
|
@@ -112,7 +108,6 @@ D:\dev\sensible-cinema-never-commit-from-here\zamples\edit_decision_lists\dvds/p
|
|
112
108
|
re-do DVD EDL's that need it :P
|
113
109
|
all dogs go to heaven...finish EDL
|
114
110
|
warn when labels exist and don't match...
|
115
|
-
kill old mencoder instances more often...
|
116
111
|
auto-download imagemagick, too
|
117
112
|
check all the many options to see if there's a "cross platform way to split files accurately" besides my hacky kludge.
|
118
113
|
can rip from a DVD-like local folder (would anybody ever need this?)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.18.
|
1
|
+
0.18.2
|
data/bin/sensible-cinema
CHANGED
@@ -25,14 +25,19 @@ require 'sane' # failure here means you haven't bundled your dependencies...[rak
|
|
25
25
|
require_relative '../lib/mencoder_wrapper'
|
26
26
|
require_relative '../lib/storage'
|
27
27
|
require_relative '../lib/edl_parser'
|
28
|
+
require_relative '../lib/mplayer_edl'
|
28
29
|
|
29
30
|
require 'tmpdir'
|
30
31
|
require_relative '../lib/swing_helpers'
|
31
32
|
require_relative '../lib/drive_info'
|
32
33
|
require 'whichr'
|
33
34
|
|
35
|
+
# must put mencoder first, as it has a working mplayer.exe in it...
|
34
36
|
ENV['PATH'] = ENV['PATH'] + ';' + File.expand_path(File.dirname(__FILE__)) + '/../vendor/cache/mencoder'.to_filename
|
35
|
-
|
37
|
+
|
38
|
+
for drive in ['c', 'd', 'e']
|
39
|
+
ENV['PATH'] = ENV['PATH'] + ";#{drive}:\\Program Files\\SMPlayer;#{drive}"
|
40
|
+
end
|
36
41
|
|
37
42
|
module SensibleSwing
|
38
43
|
class MainWindow < JFrame
|
@@ -99,11 +104,31 @@ module SensibleSwing
|
|
99
104
|
@create.on_clicked {
|
100
105
|
do_copy_dvd_to_hard_drive false
|
101
106
|
}
|
107
|
+
|
108
|
+
@edl = new_jbutton( "Watch from DVD edited", false )
|
109
|
+
@edl.on_clicked {
|
110
|
+
drive, dvd_volume_name, md5sum, edl_path, descriptors = choose_dvd_and_edl_for_it
|
111
|
+
temp_dir = Dir.tmpdir
|
112
|
+
temp_file = temp_dir + '/mplayer.temp.edl'
|
113
|
+
edl_contents = MplayerEdl.convert_to_edl descriptors
|
114
|
+
File.write(temp_file, edl_contents)
|
115
|
+
title = descriptors["dvd_title_track"] || "1"
|
116
|
+
# oh the insanity...
|
117
|
+
popup = NonBlockingDialog.new("Running mplayer. To control it, use space for pause.\n
|
118
|
+
Also right and left arrows to seek, F key for full screen,
|
119
|
+
q to quit.")
|
120
|
+
# LODO dry up mplayer opts...
|
121
|
+
# LODO more user friendly re-player...
|
122
|
+
command = "mplayer dvdnav://#{title} -nocache -alang en -sid 1000 -edl #{File.expand_path temp_file} -dvd-device #{drive}"
|
123
|
+
p command
|
124
|
+
system_non_blocking command
|
125
|
+
}
|
102
126
|
|
103
|
-
@watch_unedited = new_jbutton("Watch the current DVD unedited (from hard drive)", true)
|
127
|
+
@watch_unedited = new_jbutton("Watch the current DVD unedited (from hard drive)", true)
|
104
128
|
@watch_unedited.on_clicked {
|
105
129
|
path = RubyWhich.new.which('smplayer')
|
106
|
-
|
130
|
+
path2 = RubyWhich.new.which('mplayer')
|
131
|
+
if(path.length == 0 || path2.length == 0)
|
107
132
|
# this one has its own license...
|
108
133
|
show_blocking_message_dialog("It appears that you need to install a dependency: SMPlayer.\n
|
109
134
|
Click ok to be directed to its download website, where you can download and install it.", "Lacking dependency", JOptionPane::ERROR_MESSAGE)
|
@@ -118,12 +143,15 @@ module SensibleSwing
|
|
118
143
|
if success_no_run
|
119
144
|
on_success.call
|
120
145
|
else
|
121
|
-
|
146
|
+
Thread.new {
|
147
|
+
sleep 5; on_success.call # start it anyway :)
|
148
|
+
}
|
149
|
+
#@after_success_once = on_success # shenanigans to be able to let that thread run...
|
122
150
|
end
|
123
151
|
end
|
124
152
|
}
|
125
153
|
|
126
|
-
@open_list = new_jbutton("Open/Edit a pre-existing DVD Edit List",
|
154
|
+
@open_list = new_jbutton("Open/Edit a pre-existing DVD Edit List", true)
|
127
155
|
@open_list.on_clicked {
|
128
156
|
dialog = FileDialog.new(self, "Pick file to edit")
|
129
157
|
dialog.set_directory EDL_DIR
|
@@ -262,7 +290,7 @@ EOL
|
|
262
290
|
download("http://downloads.sourceforge.net/project/sevenzip/7-Zip/9.20/7za920.zip", "7za920.zip")
|
263
291
|
system_blocking("unzip -o 7za920.zip") # -o means "overwrite" without prompting
|
264
292
|
# now we have 7za.exe
|
265
|
-
Kernel.print 'downloading mencoder'
|
293
|
+
Kernel.print 'downloading mencoder.7z...'
|
266
294
|
download("http://downloads.sourceforge.net/project/mplayer-win32/MPlayer%20and%20MEncoder/revision%2032492/MPlayer-rtm-svn-32492.7z", "mencoder.7z")
|
267
295
|
system_blocking("7za e mencoder.7z -y -omencoder")
|
268
296
|
Kernel.puts 'done'
|
@@ -306,8 +334,8 @@ EOL
|
|
306
334
|
def get_user_input(message, default = '')
|
307
335
|
start_time = JOptionPane.showInputDialog(message, default)
|
308
336
|
end
|
309
|
-
|
310
|
-
def
|
337
|
+
|
338
|
+
def choose_dvd_and_edl_for_it
|
311
339
|
drive, dvd_volume_name, md5sum = choose_dvd_drive
|
312
340
|
puts "#{drive}, #{dvd_volume_name}, #{md5sum}"
|
313
341
|
edit_list_path = single_edit_list_matches_dvd(md5sum)
|
@@ -317,9 +345,14 @@ EOL
|
|
317
345
|
fc.set_directory EDL_DIR
|
318
346
|
edit_list_path = fc.go
|
319
347
|
end
|
320
|
-
|
348
|
+
raise 'cancelled' unless edit_list_path
|
321
349
|
descriptors = EdlParser.parse_file edit_list_path
|
350
|
+
return drive, dvd_volume_name, md5sum, edit_list_path, descriptors
|
351
|
+
end
|
322
352
|
|
353
|
+
def do_copy_dvd_to_hard_drive should_prompt_for_start_and_end_times, want_full_list = false
|
354
|
+
drive, dvd_volume_name, md5sum, edit_list_path, descriptors = choose_dvd_and_edl_for_it
|
355
|
+
|
323
356
|
dvd_title = descriptors['title'] || dvd_volume_name
|
324
357
|
|
325
358
|
fc = new_filechooser
|
@@ -347,9 +380,9 @@ EOL
|
|
347
380
|
a = File.open(File.dirname(save_to) + "/test_file_to_see_if_we_have_permission_to_write_to_this_folder", "w")
|
348
381
|
a.close
|
349
382
|
File.delete a.path
|
350
|
-
dvd_title_track = descriptors["dvd_title_track"]
|
383
|
+
dvd_title_track = descriptors["dvd_title_track"] || "1"
|
351
384
|
# how does save_to map to fulli?
|
352
|
-
fulli = save_to
|
385
|
+
fulli = MencoderWrapper.calculate_final_filename save_to
|
353
386
|
if want_full_list
|
354
387
|
# make it create a dummy response file for us :)
|
355
388
|
start_time = "00:00"
|
@@ -416,7 +449,7 @@ EOL
|
|
416
449
|
@progress_bar.visible=false
|
417
450
|
@buttons.each{|b| b.set_enabled true}
|
418
451
|
if success
|
419
|
-
saved_to = save_to + '.avi'
|
452
|
+
saved_to = save_to + '.avi'
|
420
453
|
if @after_success_once
|
421
454
|
@after_success_once.call saved_to
|
422
455
|
else
|
data/lib/mencoder_wrapper.rb
CHANGED
@@ -34,10 +34,15 @@ class MencoderWrapper
|
|
34
34
|
out + "call mencoder dvdnav://#{@dvd_title_track} -of mpeg -mpegopts format=dvd:tsaf -alang en -nocache -sid 1000 -oac #{audio_codec} #{video_opts} -ovc lavc -o #{@big_temp} -dvd-device #{this_drive} && echo got_file > #{@big_temp}.done\n"
|
35
35
|
end
|
36
36
|
|
37
|
+
def calculate_final_filename to_here_final_file
|
38
|
+
@big_temp = to_here_final_file + ".fulli_unedited.tmp.mpg"
|
39
|
+
end
|
40
|
+
|
37
41
|
# called from the UI...
|
38
42
|
def get_bat_commands these_settings, this_drive, to_here_final_file, start_here = nil, end_here = nil, dvd_title_track = "1", delete_partials = false
|
39
43
|
combined = VLCProgrammer.convert_incoming_to_split_sectors these_settings
|
40
44
|
@dvd_title_track = dvd_title_track
|
45
|
+
assert dvd_title_track
|
41
46
|
if start_here || end_here
|
42
47
|
raise 'need both' unless end_here && start_here
|
43
48
|
start_here = OverLayer.translate_string_to_seconds(start_here)
|
@@ -48,7 +53,7 @@ class MencoderWrapper
|
|
48
53
|
else
|
49
54
|
previous_end = 0
|
50
55
|
end
|
51
|
-
|
56
|
+
calculate_final_filename to_here_final_file
|
52
57
|
out = get_header this_drive, these_settings
|
53
58
|
@idx = 0
|
54
59
|
combined.each {|start, endy, type|
|
data/lib/mplayer_edl.rb
CHANGED
@@ -15,20 +15,18 @@ This file is part of Sensible Cinema.
|
|
15
15
|
You should have received a copy of the GNU General Public License
|
16
16
|
along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
=end
|
18
|
+
|
18
19
|
require_relative 'overlayer'
|
20
|
+
require_relative 'vlc_programmer'
|
19
21
|
|
20
22
|
class MplayerEdl
|
21
23
|
def self.convert_to_edl specs
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
}
|
24
|
+
combined = VLCProgrammer.convert_incoming_to_split_sectors specs
|
25
|
+
out = ''
|
26
|
+
map = {:mute => 1, :blank => 0}
|
27
|
+
for start, endy, type in combined
|
28
|
+
out += "#{start} #{endy} #{map[type]}\n"
|
27
29
|
end
|
28
|
-
|
29
|
-
out.sort.each{|start, endy, metric|
|
30
|
-
real_out += "#{start} #{endy} #{metric}\n"
|
31
|
-
}
|
32
|
-
real_out
|
30
|
+
out
|
33
31
|
end
|
34
32
|
end
|
data/lib/vlc_programmer.rb
CHANGED
@@ -24,6 +24,8 @@ class VLCProgrammer
|
|
24
24
|
@overlayer.translate_time_to_human_readable s
|
25
25
|
end
|
26
26
|
|
27
|
+
# divides up mutes and blanks so that they don't overlap, preferring blanks over mutes
|
28
|
+
# returns it like [[start,end,type], [s,e,t]...] type like :blank and :mute
|
27
29
|
def self.convert_incoming_to_split_sectors incoming
|
28
30
|
mutes = incoming["mutes"] || {}
|
29
31
|
blanks = incoming["blank_outs"] || {}
|
@@ -36,7 +38,7 @@ class VLCProgrammer
|
|
36
38
|
puts 'warning--detected an end before a start' if e < s
|
37
39
|
}
|
38
40
|
|
39
|
-
#
|
41
|
+
# VLCProgrammer.convert_to_full_xspf({ "mutes" => {5=> 7}, "blank_outs" => {6=>7} } )
|
40
42
|
# should mute 5-6, skip 6-7
|
41
43
|
combined.each_with_index{|(start, endy, type), index|
|
42
44
|
next if index == 0 # nothing to do there..
|
data/sensible-cinema.gemspec
CHANGED
data/spec/mplayer_edl.spec.rb
CHANGED
@@ -53,11 +53,15 @@ module SensibleSwing
|
|
53
53
|
it "should modify path to have mencder available, and ffmpeg, and download them on the fly" do
|
54
54
|
ENV['PATH'].should include("mencoder")
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
|
+
it "should not modify path to have mplayer available" do
|
58
|
+
ENV['PATH'].should_not include("mplayer")
|
59
|
+
end
|
60
|
+
|
57
61
|
before do
|
58
62
|
@subject = MainWindow.new
|
59
63
|
@subject.stub!(:choose_dvd_drive) {
|
60
|
-
["
|
64
|
+
["mock_dvd_drive", "Volume", "19d121ae8dc40cdd70b57ab7e8c74f76"] # happiest baby on the block
|
61
65
|
}
|
62
66
|
@subject.stub!(:get_mencoder_commands) { |*args|
|
63
67
|
args[-5].should match(/abc/)
|
@@ -90,10 +94,12 @@ module SensibleSwing
|
|
90
94
|
end
|
91
95
|
|
92
96
|
it "should be able to do a normal copy to hard drive, edited" do
|
93
|
-
@subject.do_copy_dvd_to_hard_drive(false).should == [false, "abc.
|
97
|
+
@subject.do_copy_dvd_to_hard_drive(false).should == [false, "abc.fulli_unedited.tmp.mpg"]
|
94
98
|
File.exist?('test_file_to_see_if_we_have_permission_to_write_to_this_folder').should be false
|
95
99
|
end
|
96
100
|
|
101
|
+
it "should have a good default title of 1"
|
102
|
+
|
97
103
|
it "should call through to explorer for the full thing" do
|
98
104
|
@subject.do_copy_dvd_to_hard_drive(false)
|
99
105
|
@subject.background_thread.join
|
@@ -103,13 +109,13 @@ module SensibleSwing
|
|
103
109
|
end
|
104
110
|
|
105
111
|
it "should be able to return the full list if it already exists" do
|
106
|
-
FileUtils.touch "abc.
|
107
|
-
@subject.do_copy_dvd_to_hard_drive(false,true).should == [true, "abc.
|
108
|
-
FileUtils.rm "abc.
|
112
|
+
FileUtils.touch "abc.fulli_unedited.tmp.mpg.done"
|
113
|
+
@subject.do_copy_dvd_to_hard_drive(false,true).should == [true, "abc.fulli_unedited.tmp.mpg"]
|
114
|
+
FileUtils.rm "abc.fulli_unedited.tmp.mpg.done"
|
109
115
|
end
|
110
116
|
|
111
117
|
it "should call explorer for the we can't reach this path of opening a partial without telling it what to do with it" do
|
112
|
-
@subject.do_copy_dvd_to_hard_drive(true).should == [false, "abc.
|
118
|
+
@subject.do_copy_dvd_to_hard_drive(true).should == [false, "abc.fulli_unedited.tmp.mpg"]
|
113
119
|
@subject.background_thread.join
|
114
120
|
@args[-2].should == 1
|
115
121
|
@args[-3].should == "01:00"
|
@@ -139,20 +145,17 @@ module SensibleSwing
|
|
139
145
|
|
140
146
|
|
141
147
|
it "if the .done file exists, it should directly call smplayer" do
|
142
|
-
FileUtils.touch "abc.
|
148
|
+
FileUtils.touch "abc.fulli_unedited.tmp.mpg.done"
|
143
149
|
@subject.instance_variable_get(:@watch_unedited).simulate_click
|
144
|
-
@command.should == "smplayer abc.
|
145
|
-
FileUtils.rm "abc.
|
150
|
+
@command.should == "smplayer abc.fulli_unedited.tmp.mpg"
|
151
|
+
FileUtils.rm "abc.fulli_unedited.tmp.mpg.done"
|
146
152
|
end
|
147
153
|
|
148
|
-
it "if the .done file does not exist, it should call
|
149
|
-
@subject.
|
150
|
-
@subject.
|
151
|
-
@command.should == nil # scary timing spec
|
152
|
-
@subject.background_thread.join
|
153
|
-
# should have cleaned up...
|
154
|
+
it "if the .done file does not exist, it should call smplayer ja" do
|
155
|
+
@subject.stub!(:sleep) {} # speed this up...
|
156
|
+
@subject.instance_variable_get(:@watch_unedited).simulate_click.join
|
154
157
|
@subject.after_success_once.should == nil
|
155
|
-
@command.should_not == nil
|
158
|
+
@command.should_not == nil # scary timing spec
|
156
159
|
end
|
157
160
|
|
158
161
|
it "should create a new file for ya" do
|
@@ -172,9 +175,17 @@ module SensibleSwing
|
|
172
175
|
end
|
173
176
|
end
|
174
177
|
|
175
|
-
it "should display unique" do
|
178
|
+
it "should display unique disc in an input box" do
|
176
179
|
@subject.instance_variable_get(:@display_unique).simulate_click.should == "01:00"
|
177
180
|
end
|
178
181
|
|
182
|
+
it "should create an edl" do
|
183
|
+
@subject.instance_variable_get(:@edl).simulate_click
|
184
|
+
|
185
|
+
@command.should match(/mplayer.*-edl/)
|
186
|
+
@command.should match(/-dvd-device /)
|
187
|
+
p @command
|
188
|
+
end
|
189
|
+
|
179
190
|
end
|
180
191
|
end
|