sensible-cinema 0.19.0 → 0.19.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +5 -0
- data/README +9 -9
- data/Rakefile +3 -1
- data/TODO +11 -7
- data/VERSION +1 -1
- data/bin/sensible-cinema +53 -46
- data/create or edit sensible cinema decision list files.bat +1 -1
- data/how_to_create.txt +6 -6
- data/lib/edl_parser.rb +64 -3
- data/lib/mencoder_wrapper.rb +4 -3
- data/lib/mplayer_edl.rb +2 -1
- data/lib/vlc_programmer.rb +1 -52
- data/sensible-cinema.gemspec +3 -2
- data/spec/edl_parser.spec.rb +11 -1
- data/spec/go_line.bat +1 -0
- data/spec/mencoder_wrapper.spec.rb +1 -1
- data/spec/sensible_cinema_gui.spec.rb +70 -20
- data/spec/vlc_programmer.spec.rb +5 -0
- data/zamples/edit_decision_lists/dvds/COOL_RUNNINGS.txt +4 -7
- metadata +4 -3
data/ChangeLog
CHANGED
data/README
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
Sensible-cinema (also known to us as "paranoid cinema" [inside joke ha ha] ) is a program that allows you to apply
|
2
|
-
programmed
|
2
|
+
programmed delete lists (i.e. Edit Decision Lists [2]) to DVD's you already own.
|
3
3
|
|
4
4
|
I.e. you can edit a DVD to "mute out" or skip certain scenes.
|
5
5
|
|
6
6
|
It is essentially a linear editor [1] that applies Edit Decision Lists [2] to videos, by wrapping
|
7
|
-
a few freely available open source programs [3]
|
8
|
-
to accomplish the editing for you. Then you can sit back and relax as you watch
|
7
|
+
a few freely available open source programs [3]
|
8
|
+
to accomplish the editing for you. Then you can sit back and relax as you watch the "sensible"
|
9
9
|
version of your DVD.
|
10
10
|
|
11
|
-
To use it, basically install it then run it (see installation
|
11
|
+
To use it, basically install it then run it (see installation, below).
|
12
12
|
It will come up with some windows where you choose what you want to do
|
13
13
|
|
14
|
-
If you try to make
|
14
|
+
If you try to make a copy of your DVD, note that it will take about one and a half times
|
15
15
|
as long as the playtime of the movie itself, so budget some time for it.
|
16
16
|
|
17
17
|
Also note that just because a video lacks profanity...does not immediately make it an inspiring experience.
|
@@ -26,7 +26,7 @@ Enjoy your movies!
|
|
26
26
|
|
27
27
|
[1] http://en.wikipedia.org/wiki/Linear_video_editing
|
28
28
|
[2] http://en.wikipedia.org/wiki/Edit_decision_list
|
29
|
-
[3] mostly GPL programs, see http://www.gnu.org/licenses/
|
29
|
+
[3] mostly GPL programs, see http://www.gnu.org/licenses/ VLC Media Player, Mplayer/mencoder, ffmpeg, etc.
|
30
30
|
[4] http://lds.org/library/display/0,4945,161-1-11-1,00.html search for the word "wholesome"
|
31
31
|
|
32
32
|
== Installation ==
|
@@ -35,7 +35,7 @@ To install, download the latest .zip versioned file from: http://rogerdpack.t28.
|
|
35
35
|
then unzip it (right click -> Extract all)
|
36
36
|
then "click into it" and search for and run the file "run sensible cinema.bat"
|
37
37
|
|
38
|
-
== Creating Your Own
|
38
|
+
== Creating Your Own Delete Lists, or modifying previously existing ones ==
|
39
39
|
|
40
40
|
See the accompanied how_to_create.txt file.
|
41
41
|
|
@@ -56,7 +56,7 @@ A. Probably give them the original DVD and a link to sensible-cinema :)
|
|
56
56
|
|
57
57
|
== Caveats ==
|
58
58
|
|
59
|
-
NB that "someone" has to create a
|
59
|
+
NB that "someone" has to create a delete list, per DVD.
|
60
60
|
If one doesn't yet exist for the DVD you want edited,
|
61
61
|
you could employ somebody to create it, or create it yourself. Make sure to submit it
|
62
62
|
back to us when you're done, so that everyone can benefit from it.
|
@@ -168,7 +168,7 @@ to your EDL and try again.
|
|
168
168
|
|
169
169
|
Also if your DVD playback has no audio, try the "lavc" setting, above. And report it (see feedback).
|
170
170
|
|
171
|
-
It can fail also because
|
171
|
+
It can fail also because a deletion is past end of DVD, or
|
172
172
|
Also note that if your DVD has scratches that cause it to skip, the time signatures will be off after that point,
|
173
173
|
so clean your discs and try again!
|
174
174
|
|
data/Rakefile
CHANGED
@@ -114,6 +114,8 @@ end
|
|
114
114
|
|
115
115
|
desc 'j -S rake bundle_dependencies create_distro_dir ... (releases with clean cache dir, which we need now)'
|
116
116
|
task 'full_release' => [:bundle_dependencies, :create_distro_dir, :build] do # :release sigh
|
117
|
-
|
117
|
+
gems = Dir['pkg/*.gem']
|
118
|
+
gems[0..-2].each{|f| File.delete f} # kill old versions...
|
119
|
+
system("#{Gem.ruby} -S gem push #{gems[-1]}")
|
118
120
|
puts "don't forget to blog about it...and upload .zip of it..."
|
119
121
|
end
|
data/TODO
CHANGED
@@ -3,20 +3,23 @@
|
|
3
3
|
== up next release ==
|
4
4
|
|
5
5
|
edit lists:
|
6
|
-
cool runnings
|
7
|
-
|
8
|
-
|
6
|
+
cool runnings EDL
|
7
|
+
stuff from paper
|
8
|
+
less "need java first" messages
|
9
|
+
|
9
10
|
== slightly lower than that, somewhat ordered ==
|
10
11
|
|
12
|
+
@license: requires legal DVD's to be present
|
13
|
+
can you forceidx on the original copy and have mplayer replay EDL in realtime accurately or not?
|
11
14
|
linearize edl's
|
12
15
|
don't use them linear, just linearize
|
16
|
+
not this release
|
13
17
|
|
14
18
|
edit lists:
|
15
19
|
temple
|
16
|
-
cool runnings
|
17
20
|
cars
|
18
21
|
compare computer DVD timings with physical player's timings...
|
19
|
-
if same, add imdb todo's here
|
22
|
+
if same, add imdb todo's up here
|
20
23
|
mpeg is lossy (at least my current one pass conversion is)
|
21
24
|
check the DVD burning experience too...
|
22
25
|
could check if DVD Flick handles *oversize* files well, for information sake
|
@@ -28,17 +31,18 @@
|
|
28
31
|
beta release/rinse and repeat with various ppl (once it's releasable...)
|
29
32
|
a real'ish-er website
|
30
33
|
mailing list, link to it
|
34
|
+
button to mail/submit :)
|
31
35
|
play a bigger noise when totally done...(dvd flick'ish...)
|
32
36
|
propaganda-ize
|
33
37
|
advertise in christian places
|
34
|
-
alternative.to
|
35
38
|
blogs that have ever mentioned clearplay :P
|
36
39
|
free google adwords (?)
|
37
40
|
advertise urug, ruby flow :)
|
38
|
-
add they 'play from unedited till it hits the first bad spot
|
41
|
+
add they 'play from unedited till it hits the first bad spot, if still useful
|
39
42
|
|
40
43
|
== DVD backlog (unordered, some very low prio, basically never do) ==
|
41
44
|
|
45
|
+
dvdnav versus dvd for mplayer edl?
|
42
46
|
disallow choosing empty drive? fail more gracefully? (issue 11)
|
43
47
|
some status bar that shows which DVD is in currently, how many match it, et al (pre button)
|
44
48
|
splitter abs. coords option
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.19.
|
1
|
+
0.19.1
|
data/bin/sensible-cinema
CHANGED
@@ -45,17 +45,17 @@ module SensibleSwing
|
|
45
45
|
|
46
46
|
class MainWindow < JFrame
|
47
47
|
|
48
|
-
def new_jbutton title, only_on_create_mode
|
48
|
+
def new_jbutton title, only_on_create_mode, add = false
|
49
49
|
button = JButton.new title
|
50
50
|
button.set_bounds(44, @starting_button_y, @button_width, 23)
|
51
51
|
|
52
|
-
if
|
53
|
-
|
54
|
-
increment_button_location
|
55
|
-
@panel.add button
|
56
|
-
@buttons << button
|
57
|
-
end
|
52
|
+
if ARGV.index("--create-mode")
|
53
|
+
add = true if only_on_create_mode
|
58
54
|
else
|
55
|
+
add = true if !only_on_create_mode
|
56
|
+
end
|
57
|
+
|
58
|
+
if add
|
59
59
|
increment_button_location
|
60
60
|
@panel.add button
|
61
61
|
@buttons << button
|
@@ -126,41 +126,28 @@ module SensibleSwing
|
|
126
126
|
|
127
127
|
@watch_unedited = new_jbutton("Watch a DVD unedited (while grabbing to hard drive)", true)
|
128
128
|
@watch_unedited.on_clicked {
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
show_blocking_message_dialog("It appears that you need to install a dependency: SMPlayer.\n
|
134
|
-
Click ok to be directed to its download website, where you can download and install it.", "Lacking dependency", JOptionPane::ERROR_MESSAGE)
|
135
|
-
system_non_blocking("start http://smplayer.sourceforge.net/downloads.php")
|
136
|
-
System.exit(1)
|
137
|
-
else
|
138
|
-
success_no_run, wrote_to_here_fulli = do_copy_dvd_to_hard_drive false, true
|
139
|
-
sleep 5 unless success_no_run
|
140
|
-
command = "smplayer #{wrote_to_here_fulli}"
|
141
|
-
system_non_blocking command
|
142
|
-
end
|
129
|
+
success_no_run, wrote_to_here_fulli = do_copy_dvd_to_hard_drive false, true
|
130
|
+
sleep 5 unless success_no_run
|
131
|
+
command = "smplayer #{wrote_to_here_fulli}"
|
132
|
+
system_non_blocking command
|
143
133
|
}
|
144
134
|
|
145
135
|
@preview_section = new_jbutton( "Preview a certain time frame (edited)", true )
|
146
136
|
@preview_section.on_clicked {
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
else
|
154
|
-
@after_success_once = on_success # shenanigans to be able to let that thread run...
|
155
|
-
end
|
137
|
+
do_copy_dvd_to_hard_drive true
|
138
|
+
}
|
139
|
+
|
140
|
+
@preview_section_unedited = new_jbutton("Preview a certain time frame (unedited)", true)
|
141
|
+
@preview_section_unedited.on_clicked {
|
142
|
+
do_copy_dvd_to_hard_drive true, false, true
|
156
143
|
}
|
157
144
|
|
158
145
|
@rerun_preview = new_jbutton( "Re-run most recently watched preview time frame", true )
|
159
146
|
@rerun_preview.on_clicked {
|
160
|
-
repeat_last_copy_dvd_to_hard_drive
|
147
|
+
repeat_last_copy_dvd_to_hard_drive
|
161
148
|
}
|
162
149
|
|
163
|
-
@open_list = new_jbutton("Open
|
150
|
+
@open_list = new_jbutton("Open a Delete List", true)
|
164
151
|
@open_list.on_clicked {
|
165
152
|
dialog = FileDialog.new(self, "Pick file to edit")
|
166
153
|
dialog.set_directory EDL_DIR
|
@@ -168,7 +155,7 @@ module SensibleSwing
|
|
168
155
|
open_file_to_edit_it filename if filename
|
169
156
|
}
|
170
157
|
|
171
|
-
@create_new_edl_for_current_dvd = new_jbutton("Create new
|
158
|
+
@create_new_edl_for_current_dvd = new_jbutton("Create new Delete List for a DVD", true)
|
172
159
|
@create_new_edl_for_current_dvd.on_clicked do
|
173
160
|
drive, volume, md5 = choose_dvd_drive
|
174
161
|
name = get_user_input("Enter DVD name for #{volume}")
|
@@ -214,7 +201,7 @@ EOL
|
|
214
201
|
increment_button_location
|
215
202
|
increment_button_location
|
216
203
|
|
217
|
-
@exit = new_jbutton("Exit", false).on_clicked {
|
204
|
+
@exit = new_jbutton("Exit", false, true).on_clicked {
|
218
205
|
self.close
|
219
206
|
}
|
220
207
|
|
@@ -234,6 +221,7 @@ EOL
|
|
234
221
|
end
|
235
222
|
|
236
223
|
def show_blocking_license_accept_dialog program, license_name, license_url_should_also_be_embedded_by_you_in_message, title = 'Confirm Acceptance of License Agreement', message = nil
|
224
|
+
puts 'Please confirm license agreement in an open window'
|
237
225
|
old = ['no', 'yes', 'ok'].map{|name| 'OptionPane.' + name + 'ButtonText'}.map{|name| [name, UIManager.get(name)]}
|
238
226
|
UIManager.put("OptionPane.yesButtonText", 'Accept')
|
239
227
|
UIManager.put("OptionPane.noButtonText", 'View License')
|
@@ -288,6 +276,19 @@ EOL
|
|
288
276
|
Kernel.puts 'done'
|
289
277
|
end
|
290
278
|
end
|
279
|
+
|
280
|
+
if ARGV.index('--create-mode')
|
281
|
+
# they're going to want these dependencies
|
282
|
+
path = RubyWhich.new.which('smplayer')
|
283
|
+
path2 = RubyWhich.new.which('mplayer')
|
284
|
+
if(path.length == 0 || path2.length == 0)
|
285
|
+
# this one has its own license...
|
286
|
+
show_blocking_message_dialog("It appears that you need to install a dependency: SMPlayer.\n
|
287
|
+
Click ok to be directed to its download website, where you can download and install it.", "Lacking dependency", JOptionPane::ERROR_MESSAGE)
|
288
|
+
system_non_blocking("start http://smplayer.sourceforge.net/downloads.php")
|
289
|
+
System.exit(1)
|
290
|
+
end
|
291
|
+
end
|
291
292
|
end
|
292
293
|
|
293
294
|
def open_file_to_edit_it filename
|
@@ -331,8 +332,8 @@ EOL
|
|
331
332
|
start_time = JOptionPane.showInputDialog(message, default)
|
332
333
|
end
|
333
334
|
|
334
|
-
def parse_edl path
|
335
|
-
EdlParser.parse_file path
|
335
|
+
def parse_edl path, ignore_settings = false
|
336
|
+
EdlParser.parse_file path, ignore_settings
|
336
337
|
end
|
337
338
|
|
338
339
|
def choose_dvd_and_edl_for_it
|
@@ -343,7 +344,7 @@ EOL
|
|
343
344
|
edit_list_path = single_edit_list_matches_dvd(md5sum)
|
344
345
|
if !edit_list_path
|
345
346
|
fc = FileDialog.new(self)
|
346
|
-
fc.set_title "Please pick a DVD
|
347
|
+
fc.set_title "Please pick a DVD Delete List File"
|
347
348
|
fc.set_directory EDL_DIR
|
348
349
|
edit_list_path = fc.go
|
349
350
|
end
|
@@ -359,6 +360,9 @@ EOL
|
|
359
360
|
end
|
360
361
|
[drive, dvd_volume_name, md5sum, edit_list_path, descriptors]
|
361
362
|
end
|
363
|
+
# reload it just in case it has changed on disk
|
364
|
+
@_choose_dvd_and_edl_for_it[4] = parse_edl(@_choose_dvd_and_edl_for_it[3])
|
365
|
+
@_choose_dvd_and_edl_for_it
|
362
366
|
end
|
363
367
|
|
364
368
|
def get_title_track descriptors
|
@@ -381,12 +385,15 @@ EOL
|
|
381
385
|
end
|
382
386
|
end
|
383
387
|
|
384
|
-
def do_copy_dvd_to_hard_drive should_prompt_for_start_and_end_times, exit_early_if_fulli_exists = false
|
388
|
+
def do_copy_dvd_to_hard_drive should_prompt_for_start_and_end_times, exit_early_if_fulli_exists = false, ignore_settings = false
|
385
389
|
drive, dvd_volume_name, md5sum, edit_list_path, descriptors = choose_dvd_and_edl_for_it
|
390
|
+
|
391
|
+
descriptors = parse_edl(edit_list_path, ignore_settings)
|
392
|
+
|
386
393
|
# LODO allow for spaces in the save_to filename
|
387
394
|
if should_prompt_for_start_and_end_times
|
388
395
|
# only show it once :)
|
389
|
-
@show_block ||= show_blocking_message_dialog("Ok, let's preview just a portion of it. \nNote that you'll want to preview a section that wholly includes
|
396
|
+
@show_block ||= show_blocking_message_dialog("Ok, let's preview just a portion of it. \nNote that you'll want to preview a section that wholly includes a deletion section in it\n 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.\nAlso note that the first time you preview a section of a video, it will take like 20 minutes as it sets up the video for previewing.\nSubsequent previews will be faster, though, as long as you use the same filename.", "Preview") || true
|
390
397
|
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)", Storage['start_time'])
|
391
398
|
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)", Storage['end_time'])
|
392
399
|
unless start_time and end_time
|
@@ -410,7 +417,7 @@ EOL
|
|
410
417
|
|
411
418
|
dvd_title_track = get_title_track(descriptors)
|
412
419
|
run_mplayer = should_prompt_for_start_and_end_times || exit_early_if_fulli_exists
|
413
|
-
generate_and_run_bat_file save_to, edit_list_path, descriptors, drive, dvd_title, start_time, end_time, dvd_title_track, run_mplayer
|
420
|
+
generate_and_run_bat_file save_to, edit_list_path, descriptors, drive, dvd_title, start_time, end_time, dvd_title_track, run_mplayer, !ignore_settings
|
414
421
|
[false, fulli] # false means it's running in a background thread :P
|
415
422
|
end
|
416
423
|
|
@@ -418,13 +425,13 @@ EOL
|
|
418
425
|
DriveInfo.get_drive_with_most_space_with_slash
|
419
426
|
end
|
420
427
|
|
421
|
-
def get_mencoder_commands descriptors, drive, save_to, start_time, end_time, dvd_title_track
|
422
|
-
MencoderWrapper.get_bat_commands descriptors, drive, save_to, start_time, end_time, dvd_title_track
|
428
|
+
def get_mencoder_commands descriptors, drive, save_to, start_time, end_time, dvd_title_track, require_deletion_entry
|
429
|
+
MencoderWrapper.get_bat_commands descriptors, drive, save_to, start_time, end_time, dvd_title_track, true, require_deletion_entry # delete partials...
|
423
430
|
end
|
424
431
|
|
425
|
-
def generate_and_run_bat_file save_to, edit_list_path, descriptors, drive, dvd_title, start_time, end_time, dvd_title_track, run_mplayer
|
426
|
-
Storage['last_params'] = [save_to, edit_list_path, descriptors, drive, dvd_title, start_time, end_time, dvd_title_track, run_mplayer]
|
427
|
-
commands = get_mencoder_commands descriptors, drive, save_to, start_time, end_time, dvd_title_track
|
432
|
+
def generate_and_run_bat_file save_to, edit_list_path, descriptors, drive, dvd_title, start_time, end_time, dvd_title_track, run_mplayer, require_deletion_entry
|
433
|
+
Storage['last_params'] = [save_to, edit_list_path, descriptors, drive, dvd_title, start_time, end_time, dvd_title_track, run_mplayer, require_deletion_entry]
|
434
|
+
commands = get_mencoder_commands descriptors, drive, save_to, start_time, end_time, dvd_title_track, require_deletion_entry
|
428
435
|
temp_dir = Dir.tmpdir
|
429
436
|
temp_file = temp_dir + '/vlc.temp.bat'
|
430
437
|
File.write(temp_file, commands)
|
@@ -443,7 +450,7 @@ EOL
|
|
443
450
|
# LODO warn if they will overwrite a file in the end...
|
444
451
|
end
|
445
452
|
|
446
|
-
attr_accessor :background_thread, :after_success_once
|
453
|
+
attr_accessor :background_thread, :after_success_once, :buttons
|
447
454
|
|
448
455
|
def run_create_commands batch_commands, save_to, run_mplayer
|
449
456
|
@buttons.each{|b| b.set_enabled false}
|
@@ -3,4 +3,4 @@
|
|
3
3
|
@set RUBYOPT=
|
4
4
|
@echo This window will display lots of debug message output!
|
5
5
|
@cd sensible-cinema && java -cp "./vendor/cache/jruby-complete-1.5.5.jar" org.jruby.Main bin\sensible-cinema --create-mode || echo you need to install java first! please report back the error you see! && pause
|
6
|
-
@
|
6
|
+
@taskkill /f /im mencoder.exe
|
data/how_to_create.txt
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
-
You create
|
1
|
+
You create a delete list for sensible cinema to use against whatever you want.
|
2
2
|
|
3
|
-
An
|
3
|
+
An delete list looks something like this example:
|
4
4
|
|
5
5
|
https://github.com/rdp/sensible-cinema/blob/master/zamples/edit_decision_lists/example_edit_decision_list.txt
|
6
6
|
|
7
|
-
Basically your job is to create an appropriate file (like that one)
|
7
|
+
Basically your job is to create an appropriate file (like that one),
|
8
8
|
then start sensible-cinema and instruct it to use your new file.
|
9
9
|
|
10
10
|
For a DVD, the steps might look like this:
|
11
11
|
|
12
|
-
open Sensible cinema
|
13
|
-
insert DVD, click "create new
|
12
|
+
open Sensible cinema "create mode"
|
13
|
+
insert DVD, click "create new" button
|
14
14
|
|
15
15
|
click "open ripped version of DVD unedited", right click, create new file, name it something.txt, right click, "open", and then select it.
|
16
16
|
|
@@ -39,7 +39,7 @@ Also after you're done, you can submit it back to the project by emailing me wit
|
|
39
39
|
|
40
40
|
Also if you want sensible-cinema to be able to auto-choose your EDL, then include its unique id (click the "Get a disk's unique id" button).
|
41
41
|
|
42
|
-
I typically like to make two
|
42
|
+
I typically like to make two delete lists per DVD. One that takes out swearing, sex, and gruesome violence, and another
|
43
43
|
"more paranoid" version that takes out basically anything that could be offensive to anybody :) ("dang", "fetch", "too tense" of scenes...)
|
44
44
|
|
45
45
|
A few pointers:
|
data/lib/edl_parser.rb
CHANGED
@@ -15,15 +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
|
+
|
19
|
+
require_relative 'overlayer'
|
20
|
+
|
18
21
|
class EdlParser
|
19
22
|
|
20
|
-
def self.parse_file filename
|
21
|
-
parse_string File.read(filename), filename
|
23
|
+
def self.parse_file filename, ignore_settings = false
|
24
|
+
parse_string File.read(filename), filename, [], ignore_settings
|
22
25
|
end
|
23
26
|
|
24
27
|
# better eye-ball these before letting people run them, eh?
|
25
28
|
# but I couldn't think of any other way
|
26
|
-
def self.parse_string string, filename, ok_categories_array = []
|
29
|
+
def self.parse_string string, filename, ok_categories_array = [], ignore_settings = false
|
27
30
|
string = '{' + string + "\n}"
|
28
31
|
if filename
|
29
32
|
raw = eval(string, binding, filename)
|
@@ -31,9 +34,14 @@ class EdlParser
|
|
31
34
|
raw = eval string
|
32
35
|
end
|
33
36
|
|
37
|
+
raise SyntaxError.new("maybe missing quotation marks?" + string) if raw.keys.contain?(nil)
|
38
|
+
|
34
39
|
# mutes and blank_outs need to be special parsed into arrays...
|
35
40
|
mutes = raw["mutes"] || []
|
36
41
|
blanks = raw["blank_outs"] || []
|
42
|
+
if ignore_settings
|
43
|
+
mutes = blanks = []
|
44
|
+
end
|
37
45
|
raw["mutes"] = convert_to_timestamp_arrays(mutes, ok_categories_array)
|
38
46
|
raw["blank_outs"] = convert_to_timestamp_arrays(blanks, ok_categories_array)
|
39
47
|
raw
|
@@ -67,5 +75,58 @@ class EdlParser
|
|
67
75
|
end
|
68
76
|
out
|
69
77
|
end
|
78
|
+
|
79
|
+
# divides up mutes and blanks so that they don't overlap, preferring blanks over mutes
|
80
|
+
# returns it like [[start,end,type], [s,e,t]...] type like :blank and :mute
|
81
|
+
def self.convert_incoming_to_split_sectors incoming, add_this_to_mutes = 0
|
82
|
+
mutes = incoming["mutes"] || {}
|
83
|
+
blanks = incoming["blank_outs"] || {}
|
84
|
+
mutes = mutes.map{|k, v| [OverLayer.translate_string_to_seconds(k), OverLayer.translate_string_to_seconds(v) + add_this_to_mutes, :mute]}
|
85
|
+
blanks = blanks.map{|k, v| [OverLayer.translate_string_to_seconds(k), OverLayer.translate_string_to_seconds(v), :blank]}
|
86
|
+
|
87
|
+
combined = (mutes+blanks).sort
|
88
|
+
|
89
|
+
combined.each{|s, e, t|
|
90
|
+
puts 'warning--detected an end before a start' if e < s
|
91
|
+
}
|
92
|
+
|
93
|
+
# VLCProgrammer.convert_to_full_xspf({ "mutes" => {5=> 7}, "blank_outs" => {6=>7} } )
|
94
|
+
# should mute 5-6, skip 6-7
|
95
|
+
previous = combined[0]
|
96
|
+
combined.each_with_index{|(start, endy, type), index|
|
97
|
+
next if index == 0 # nothing to do there..
|
98
|
+
previous_end = previous[1]
|
99
|
+
previous_type = previous[2]
|
100
|
+
previous_start = previous[0]
|
101
|
+
if type == :blank
|
102
|
+
raise 'no overlap like that allowed as of yet' unless previous_end <= endy
|
103
|
+
if previous_type == :mute && previous_end > start
|
104
|
+
previous[1] = start # make it end when we start...
|
105
|
+
end
|
106
|
+
elsif type == :mute
|
107
|
+
if previous_end > start
|
108
|
+
|
109
|
+
if previous_end >= endy
|
110
|
+
combined[index] = [nil] # null it out...it's a mute subsumed by a blank apparently...
|
111
|
+
if previous_type == :mute
|
112
|
+
raise 'overlapping mute?'
|
113
|
+
end
|
114
|
+
next
|
115
|
+
else
|
116
|
+
# start mine when the last one ended...
|
117
|
+
combined[index] = [previous_end, endy, type]
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
else
|
122
|
+
raise 'unexpected'
|
123
|
+
end
|
124
|
+
previous = combined[index]
|
125
|
+
}
|
126
|
+
|
127
|
+
combined.select{|start, endy, type|
|
128
|
+
(start != nil) && (endy > start) # ignore mutes wholly contained within blanks...
|
129
|
+
}
|
130
|
+
end
|
70
131
|
|
71
132
|
end
|
data/lib/mencoder_wrapper.rb
CHANGED
@@ -16,7 +16,7 @@ This file is part of Sensible Cinema.
|
|
16
16
|
along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
=end
|
18
18
|
|
19
|
-
require_relative '
|
19
|
+
require_relative 'edl_parser'
|
20
20
|
|
21
21
|
class MencoderWrapper
|
22
22
|
|
@@ -39,8 +39,8 @@ class MencoderWrapper
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# called from the UI...
|
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
|
43
|
-
combined =
|
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, require_deletion_entry = false
|
43
|
+
combined = EdlParser.convert_incoming_to_split_sectors these_settings
|
44
44
|
@dvd_title_track = dvd_title_track
|
45
45
|
assert dvd_title_track
|
46
46
|
if start_here || end_here
|
@@ -48,6 +48,7 @@ class MencoderWrapper
|
|
48
48
|
start_here = OverLayer.translate_string_to_seconds(start_here)
|
49
49
|
end_here = OverLayer.translate_string_to_seconds(end_here)
|
50
50
|
combined.select!{|start, endy, type| start > start_here && endy < end_here }
|
51
|
+
raise "unable to find deletion entry between #{start_here} and #{end_here}" if require_deletion_entry && combined.length == 0
|
51
52
|
# it's relative now, since we rip from not the beginning
|
52
53
|
previous_end = start_here
|
53
54
|
else
|
data/lib/mplayer_edl.rb
CHANGED
@@ -21,7 +21,8 @@ require_relative 'vlc_programmer'
|
|
21
21
|
|
22
22
|
class MplayerEdl
|
23
23
|
def self.convert_to_edl specs, add_this_many_to_end = 0
|
24
|
-
|
24
|
+
# simple re-map.
|
25
|
+
combined = EdlParser.convert_incoming_to_split_sectors specs, add_this_many_to_end
|
25
26
|
out = ''
|
26
27
|
map = {:mute => 1, :blank => 0}
|
27
28
|
for start, endy, type in combined
|
data/lib/vlc_programmer.rb
CHANGED
@@ -24,57 +24,6 @@ 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
|
29
|
-
def self.convert_incoming_to_split_sectors incoming, add_this_to_mutes = 0
|
30
|
-
mutes = incoming["mutes"] || {}
|
31
|
-
blanks = incoming["blank_outs"] || {}
|
32
|
-
mutes = mutes.map{|k, v| [OverLayer.translate_string_to_seconds(k), OverLayer.translate_string_to_seconds(v) + add_this_to_mutes, :mute]}
|
33
|
-
blanks = blanks.map{|k, v| [OverLayer.translate_string_to_seconds(k), OverLayer.translate_string_to_seconds(v), :blank]}
|
34
|
-
|
35
|
-
combined = (mutes+blanks).sort
|
36
|
-
|
37
|
-
combined.each{|s, e, t|
|
38
|
-
puts 'warning--detected an end before a start' if e < s
|
39
|
-
}
|
40
|
-
|
41
|
-
# VLCProgrammer.convert_to_full_xspf({ "mutes" => {5=> 7}, "blank_outs" => {6=>7} } )
|
42
|
-
# should mute 5-6, skip 6-7
|
43
|
-
combined.each_with_index{|(start, endy, type), index|
|
44
|
-
next if index == 0 # nothing to do there..
|
45
|
-
previous = combined[index-1]
|
46
|
-
previous_end = previous[1]
|
47
|
-
previous_type = previous[2]
|
48
|
-
previous_start = previous[0]
|
49
|
-
if type == :blank
|
50
|
-
raise 'no overlap like that allowed as of yet' unless previous_end <= endy
|
51
|
-
if previous_type == :mute && previous_end > start
|
52
|
-
previous[1] = start # make it end when we start...
|
53
|
-
end
|
54
|
-
elsif type == :mute
|
55
|
-
if previous_end > start
|
56
|
-
|
57
|
-
if previous_end >= endy
|
58
|
-
combined[index] = [nil] # null it out...it's a mute subsumed by a blank apparently...
|
59
|
-
if previous_type == :mute
|
60
|
-
raise 'overlapping mute?'
|
61
|
-
end
|
62
|
-
else
|
63
|
-
# start mine when the last one ended...
|
64
|
-
combined[index] = [previous_end, endy, type]
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
else
|
70
|
-
raise 'unexpected'
|
71
|
-
end
|
72
|
-
}
|
73
|
-
|
74
|
-
combined.select{|start, endy, type|
|
75
|
-
(start != nil) && (endy > start) # ignore mutes wholly contained within blanks...
|
76
|
-
}
|
77
|
-
end
|
78
27
|
|
79
28
|
def self.convert_to_full_xspf incoming, filename = nil, drive_with_slash = nil, dvd_title_track = nil, dvd_title_name = nil
|
80
29
|
|
@@ -82,7 +31,7 @@ class VLCProgrammer
|
|
82
31
|
@filename_or_playlist_if_nil = filename
|
83
32
|
@dvd_title_track = dvd_title_track || "1"
|
84
33
|
@dvd_title_name = dvd_title_name
|
85
|
-
combined = convert_incoming_to_split_sectors incoming
|
34
|
+
combined = EdlParser.convert_incoming_to_split_sectors incoming
|
86
35
|
|
87
36
|
out = get_header
|
88
37
|
|
data/sensible-cinema.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{sensible-cinema}
|
8
|
-
s.version = "0.19.
|
8
|
+
s.version = "0.19.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Roger Pack"]
|
12
|
-
s.date = %q{2010-12-
|
12
|
+
s.date = %q{2010-12-21}
|
13
13
|
s.email = %q{rogerdpack@gmail.com}
|
14
14
|
s.executables = ["sensible-cinema", "sensible-cinema-cli"]
|
15
15
|
s.extensions = ["ext/mkrf_conf.rb"]
|
@@ -62,6 +62,7 @@ Gem::Specification.new do |s|
|
|
62
62
|
"spec/convert_image.rb",
|
63
63
|
"spec/drive_info.spec.rb",
|
64
64
|
"spec/edl_parser.spec.rb",
|
65
|
+
"spec/go_line.bat",
|
65
66
|
"spec/images/black.bmp",
|
66
67
|
"spec/images/colon.bmp",
|
67
68
|
"spec/images/hulu_0.bmp",
|
data/spec/edl_parser.spec.rb
CHANGED
@@ -38,7 +38,8 @@ describe EdlParser do
|
|
38
38
|
["01:01:00", "01:02:00", "profanity", "bodily function 1"]],
|
39
39
|
"missing_content"=>"this doesn't list some mild name calling",
|
40
40
|
"title"=>"Forever Strong", "source"=>"Hulu", "url"=>"http://www.byutv.org/watch/1790-100",
|
41
|
-
"whatever_else_you_want"=>"this is the old version of the film"
|
41
|
+
"whatever_else_you_want"=>"this is the old version of the film",
|
42
|
+
|
42
43
|
}
|
43
44
|
E.parse_string(string, nil).should == expected
|
44
45
|
end
|
@@ -90,4 +91,13 @@ describe EdlParser do
|
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
94
|
+
it "should reject misformatted files" do
|
95
|
+
proc {E.parse_string 'mutes=>["0:33", "0:34"]', 'filename'}.should raise_error(SyntaxError)
|
96
|
+
proc {E.parse_string '"mutes"=>["0:33", "0:34"]', 'filename'}.should_not raise_error
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should be able to optionally ignore settings" do
|
100
|
+
E.parse_string('"mutes"=>["0:33", "0:34"]', 'filename', [], true)['mutes'].should == []
|
101
|
+
end
|
102
|
+
|
93
103
|
end
|
data/spec/go_line.bat
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
jd -S rspec sensible_cinema_gui.spec.rb -l %*
|
@@ -208,7 +208,7 @@ describe MencoderWrapper do
|
|
208
208
|
|
209
209
|
it "should allow you to play something even if there's no edit list, just for examination sake" do
|
210
210
|
setup
|
211
|
-
proc { MencoderWrapper.get_bat_commands @settings, "e:\\", 'to_here', '00:14', '00:15'}.
|
211
|
+
proc { MencoderWrapper.get_bat_commands @settings, "e:\\", 'to_here', '00:14', '00:15', "1", false, true}.should raise_error(/unable/)
|
212
212
|
end
|
213
213
|
|
214
214
|
end
|
@@ -58,20 +58,26 @@ module SensibleSwing
|
|
58
58
|
@subject.single_edit_list_matches_dvd 'fake md5'
|
59
59
|
end
|
60
60
|
|
61
|
-
|
61
|
+
def with_clean_edl_dir_as this
|
62
|
+
FileUtils.rm_rf 'temp'
|
63
|
+
Dir.mkdir 'temp'
|
62
64
|
old_edl = MainWindow::EDL_DIR
|
65
|
+
MainWindow.const_set(:EDL_DIR, 'temp')
|
63
66
|
begin
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
+
yield
|
68
|
+
ensure
|
69
|
+
MainWindow.const_set(:EDL_DIR, old_edl)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should prompt if two EDL's match a DVD title" do
|
74
|
+
with_clean_edl_dir_as 'temp' do
|
67
75
|
MainWindow.new.single_edit_list_matches_dvd("BOBS_BIG_PLAN").should be nil
|
68
76
|
Dir.chdir 'temp' do
|
69
77
|
File.binwrite('a.txt', "\"disk_unique_id\" => \"abcdef1234\"")
|
70
78
|
File.binwrite('b.txt', "\"disk_unique_id\" => \"abcdef1234\"")
|
71
79
|
end
|
72
80
|
MainWindow.new.single_edit_list_matches_dvd("abcdef1234").should be nil
|
73
|
-
ensure
|
74
|
-
MainWindow.const_set(:EDL_DIR, old_edl)
|
75
81
|
end
|
76
82
|
end
|
77
83
|
|
@@ -89,9 +95,9 @@ module SensibleSwing
|
|
89
95
|
["mock_dvd_drive", "Volume", "19d121ae8dc40cdd70b57ab7e8c74f76"] # happiest baby on the block
|
90
96
|
}
|
91
97
|
@subject.stub!(:get_mencoder_commands) { |*args|
|
92
|
-
args[-
|
98
|
+
args[-5].should match(/abc/)
|
93
99
|
@args = args
|
94
|
-
'
|
100
|
+
'fake get_mencoder_commands'
|
95
101
|
}
|
96
102
|
@subject.stub!(:new_filechooser) {
|
97
103
|
FakeFileChooser.new
|
@@ -148,7 +154,7 @@ module SensibleSwing
|
|
148
154
|
it "should call through to explorer for the full thing" do
|
149
155
|
@subject.do_copy_dvd_to_hard_drive(false)
|
150
156
|
@subject.background_thread.join
|
151
|
-
@args[-
|
157
|
+
@args[-4].should == nil
|
152
158
|
@system_blocking_command.should match /explorer/
|
153
159
|
@system_blocking_command.should_not match /fulli/
|
154
160
|
end
|
@@ -162,17 +168,17 @@ module SensibleSwing
|
|
162
168
|
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
|
163
169
|
@subject.do_copy_dvd_to_hard_drive(true).should == [false, "abc.fulli_unedited.tmp.mpg"]
|
164
170
|
@subject.background_thread.join
|
165
|
-
@args[-
|
166
|
-
@args[-
|
171
|
+
@args[-2].should == 1
|
172
|
+
@args[-3].should == "01:00"
|
167
173
|
@command.should match /smplayer/
|
168
174
|
@command.should_not match /fulli/
|
169
175
|
end
|
170
176
|
|
171
177
|
def prompt_for_start_and_end_times
|
172
|
-
|
173
|
-
|
174
|
-
@args[-2].should ==
|
175
|
-
@
|
178
|
+
click_button(:@preview_section)
|
179
|
+
join_background_thread
|
180
|
+
@args[-2].should == 1
|
181
|
+
@args[-3].should == "01:00"
|
176
182
|
@command.should match /smplayer/
|
177
183
|
end
|
178
184
|
|
@@ -180,6 +186,21 @@ module SensibleSwing
|
|
180
186
|
prompt_for_start_and_end_times
|
181
187
|
end
|
182
188
|
|
189
|
+
temp_dir = Dir.tmpdir
|
190
|
+
|
191
|
+
def join_background_thread
|
192
|
+
@subject.background_thread.join
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should be able to preview unedited" do
|
196
|
+
@subject.stub!(:get_user_input).and_return('06:00', '07:00')
|
197
|
+
@subject.unstub!(:get_mencoder_commands)
|
198
|
+
click_button(:@preview_section_unedited)
|
199
|
+
join_background_thread
|
200
|
+
temp_file = temp_dir + '/vlc.temp.bat'
|
201
|
+
File.read(temp_file).should include("59.99")
|
202
|
+
end
|
203
|
+
|
183
204
|
it "should be able to rerun the latest start and end times with the rerun button" do
|
184
205
|
prompt_for_start_and_end_times
|
185
206
|
old_args = @args
|
@@ -190,7 +211,17 @@ module SensibleSwing
|
|
190
211
|
@command.should match(/smplayer/)
|
191
212
|
end
|
192
213
|
|
193
|
-
it "if
|
214
|
+
it "should raise if you watch an edited time frame with no edits in it" do
|
215
|
+
@subject.unstub!(:get_mencoder_commands)
|
216
|
+
proc { prompt_for_start_and_end_times }.should raise_error(/unable to find deletion entry/)
|
217
|
+
@subject.stub!(:get_user_input).and_return('06:00', '07:00')
|
218
|
+
# rspec bug: wrong backtrace: proc { prompt_for_start_and_end_times #}.should_not raise_error LODO
|
219
|
+
click_button(:@preview_section) # doesn't raise
|
220
|
+
join_background_thread
|
221
|
+
@system_blocking_command.should == "echo wrote (probably successfully) to abc.avi"
|
222
|
+
end
|
223
|
+
|
224
|
+
it "if the .done files exists, it should directly call smplayer" do
|
194
225
|
FileUtils.touch "abc.fulli_unedited.tmp.mpg.done"
|
195
226
|
@subject.instance_variable_get(:@watch_unedited).simulate_click
|
196
227
|
@command.should == "smplayer abc.fulli_unedited.tmp.mpg"
|
@@ -201,7 +232,7 @@ module SensibleSwing
|
|
201
232
|
@subject.stub!(:sleep) {} # speed this test up...
|
202
233
|
@subject.instance_variable_get(:@watch_unedited).simulate_click.join
|
203
234
|
@subject.after_success_once.should == nil
|
204
|
-
@command.should_not == nil
|
235
|
+
@command.should_not == nil
|
205
236
|
end
|
206
237
|
|
207
238
|
it "should create a new file for ya" do
|
@@ -231,12 +262,11 @@ module SensibleSwing
|
|
231
262
|
end
|
232
263
|
|
233
264
|
it "should play edl with elongated mutes" do
|
234
|
-
temp_dir = Dir.tmpdir
|
235
265
|
temp_file = temp_dir + '/mplayer.temp.edl'
|
236
266
|
click_button(:@mplayer_edl).join
|
237
267
|
wrote = File.read(temp_file)
|
238
268
|
# normally "378.0 379.1 1\n"
|
239
|
-
wrote.should include("380.
|
269
|
+
wrote.should include("380.85 1")
|
240
270
|
end
|
241
271
|
|
242
272
|
it "should only prompt for drive once" do
|
@@ -251,6 +281,18 @@ module SensibleSwing
|
|
251
281
|
count.should == 1
|
252
282
|
end
|
253
283
|
|
284
|
+
it "should allow for file to change contents while editing it" do
|
285
|
+
with_clean_edl_dir_as 'temp' do
|
286
|
+
File.binwrite('temp/a.txt', "\"disk_unique_id\" => \"abcdef1234\"")
|
287
|
+
@subject.stub!(:choose_dvd_drive) {
|
288
|
+
["mock_dvd_drive", "Volume", "abcdef1234"]
|
289
|
+
}
|
290
|
+
@subject.choose_dvd_and_edl_for_it[4]['mutes'].should == []
|
291
|
+
File.binwrite('temp/a.txt', '"disk_unique_id" => "abcdef1234","mutes"=>["0:33", "0:34"]')
|
292
|
+
@subject.choose_dvd_and_edl_for_it[4]['mutes'].should_not == []
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
254
296
|
it "should only prompt for save to filename once" do
|
255
297
|
count = 0
|
256
298
|
@subject.stub!(:new_filechooser) {
|
@@ -262,8 +304,16 @@ module SensibleSwing
|
|
262
304
|
count.should == 1
|
263
305
|
end
|
264
306
|
|
265
|
-
it "should prompt you if you need to insert a dvd"
|
307
|
+
it "should prompt you if you need to insert a dvd" do
|
308
|
+
# it does :)
|
309
|
+
end
|
266
310
|
|
311
|
+
it "should not show the normal buttons in create mode" do
|
312
|
+
MainWindow.new.buttons.length.should == 3 # exit button, two normal buttons
|
313
|
+
ARGV << "--create-mode"
|
314
|
+
MainWindow.new.buttons.length.should == 8
|
315
|
+
ARGV.pop # cleanup--why not :)
|
316
|
+
end
|
267
317
|
|
268
318
|
end
|
269
319
|
|
data/spec/vlc_programmer.spec.rb
CHANGED
@@ -92,6 +92,11 @@ describe 'VLC Programmer' do
|
|
92
92
|
a.scan(/ to /).length.should == 2 # 0->6, 7 -> end
|
93
93
|
|
94
94
|
end
|
95
|
+
|
96
|
+
it "should ignore a mute wholly within a blank" do
|
97
|
+
a = VLCProgrammer.convert_to_full_xspf({ "mutes" => {6=> 7}, "blank_outs" => {5=>8, 9=>10} } )
|
98
|
+
a.scan(/ to /).length.should == 3 # 0->5, 8 -> 9, 10 => end
|
99
|
+
end
|
95
100
|
|
96
101
|
it "should not try to save it to a file from within the xml" do
|
97
102
|
a = VLCProgrammer.convert_to_full_xspf({ "mutes" => {5=>10} } )
|
@@ -1,11 +1,8 @@
|
|
1
1
|
# comments can go after a # on any line.
|
2
2
|
"mutes" => [
|
3
3
|
"14:53.7", "14:55", "greetings sled g..",
|
4
|
-
|
5
|
-
#
|
6
|
-
#59:52 dang good apology
|
7
|
-
#1:02:08 "butt whipped"
|
8
|
-
#1:02:27 "butt whipping"
|
4
|
+
"1:02:03", "1:02:04", "butt whipped"
|
5
|
+
"1:02:36", "1:02:37", "butt whipping" #not verified
|
9
6
|
#1:01:40 "sled g... does it again"
|
10
7
|
],
|
11
8
|
|
@@ -17,8 +14,8 @@
|
|
17
14
|
"1:16:57.0" , "1:16:57.5", "bad a..",
|
18
15
|
# 15:22 irv beats his radio with pool cue should go...
|
19
16
|
"15:20", "15:30",
|
20
|
-
"59:15", "59:59",
|
21
|
-
|
17
|
+
"59:15", "59:59", "bad arsenic ...",
|
18
|
+
|
22
19
|
],
|
23
20
|
|
24
21
|
"disk_unique_id" => "5a0a43f52e5d5e705fdfaa831b38409b",
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 19
|
8
|
-
-
|
9
|
-
version: 0.19.
|
8
|
+
- 1
|
9
|
+
version: 0.19.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Roger Pack
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-12-
|
17
|
+
date: 2010-12-21 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -200,6 +200,7 @@ files:
|
|
200
200
|
- spec/convert_image.rb
|
201
201
|
- spec/drive_info.spec.rb
|
202
202
|
- spec/edl_parser.spec.rb
|
203
|
+
- spec/go_line.bat
|
203
204
|
- spec/images/black.bmp
|
204
205
|
- spec/images/colon.bmp
|
205
206
|
- spec/images/hulu_0.bmp
|