sensible-cinema 0.20.0 → 0.20.1
Sign up to get free protection for your applications and to get access to all the features.
- data/TODO +24 -6
- data/VERSION +1 -1
- data/bin/sensible-cinema +36 -25
- data/lib/edl_parser.rb +65 -45
- data/lib/mencoder_wrapper.rb +2 -2
- data/lib/mplayer_edl.rb +3 -3
- data/lib/overlayer.rb +4 -20
- data/sensible-cinema.gemspec +2 -2
- data/spec/edl_parser.spec.rb +49 -4
- data/spec/mplayer_edl.spec.rb +17 -14
- data/spec/notes +9 -0
- data/spec/sensible_cinema_gui.spec.rb +435 -409
- data/zamples/edit_decision_lists/dvds/Harry Potter 2.txt +2 -1
- data/zamples/edit_decision_lists/dvds/happiest baby on the block.txt +2 -1
- metadata +3 -3
data/TODO
CHANGED
@@ -2,18 +2,24 @@
|
|
2
2
|
|
3
3
|
== up next release ==
|
4
4
|
|
5
|
-
edl straight DVD replay:
|
5
|
+
edl straight DVD replay:
|
6
6
|
work cars
|
7
7
|
clear runnings
|
8
|
+
finalize
|
8
9
|
have ben and chris test it out
|
9
10
|
|
10
11
|
== slightly lower than that, somewhat ordered ==
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
test HP if I put the whole thing together (2 hour mark)
|
14
|
+
try it again with grabbing from DVD too
|
15
|
+
add "revision"
|
16
|
+
note: you need to offset your start times
|
17
|
+
change it to be aggressive sometimes yes, other times no
|
18
|
+
note: can make several different versions, with different filenames, and should rewatch the film after finalizing it (edited), like "grab to hard drive" and have a friend watch it, if desired.
|
19
|
+
make the other button work again (watch unedited while grabbing)
|
20
|
+
the "edited.avi" *must* be playable in WMP
|
15
21
|
don't exit program if they don't select a disk :)
|
16
|
-
if they type in a "new" start time, use that as the default end time input
|
22
|
+
if they type in a "new" start time, use that as the default end time input too
|
17
23
|
linearize edl's
|
18
24
|
don't use them linear, just linearize
|
19
25
|
mpeg is lossy (at least my current one pass conversion still is...) and smplayer can't play it right unedited
|
@@ -49,6 +55,10 @@
|
|
49
55
|
|
50
56
|
== DVD backlog (unordered, some very low prio, basically all never do) ==
|
51
57
|
|
58
|
+
@ffmpeg: do you get slower the farther into large files you are?
|
59
|
+
FHE friendly: always harddup, "watch as grabbed" button [plus other ramifications]
|
60
|
+
@ffmpeg: gop 12 for ntsc-dvd?
|
61
|
+
@ffmpeg: doesn't grab the right time frames?
|
52
62
|
@mplayer: why you can't play it when VLC can? huh? (audio sync)
|
53
63
|
can watch conference like a music video :)
|
54
64
|
can play "this section then that, with this one's audio
|
@@ -345,4 +355,12 @@ donate money to several projects I use/like :)
|
|
345
355
|
@mencoder: ripping like this results in an (avidemux, VLC) fourcc of 'ugh': mencoder2 dvdnav://1 -oac copy -ovc copy -o D:\raw_rip_mpeg_example.avi -endpos 20 -dvd-device E:\
|
346
356
|
|
347
357
|
@jruby: system("mencoder") from a button doesn't get interrupted by an exception [!]
|
348
|
-
@vlc: replay mp4's are too dark.
|
358
|
+
@vlc: replay mp4's are too dark.
|
359
|
+
|
360
|
+
@rspec: 1) EdlParser should raise for end before beginning
|
361
|
+
Failure/Error: proc{ go({"mutes"=>{105=>104.9}})}.should raise_error(/SyntaxError/)
|
362
|
+
expected Exception with message matching /SyntaxError/, got #<SyntaxError: warning--detected an end before a start 104.9 < 105.0>
|
363
|
+
# edl_parser.spec.rb:115
|
364
|
+
# :1
|
365
|
+
|
366
|
+
message confusing :)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.20.
|
1
|
+
0.20.1
|
data/bin/sensible-cinema
CHANGED
@@ -107,9 +107,9 @@ module SensibleSwing
|
|
107
107
|
do_copy_dvd_to_hard_drive false
|
108
108
|
}
|
109
109
|
|
110
|
-
@mplayer_edl = new_jbutton( "Watch DVD on computer edited realtime
|
110
|
+
@mplayer_edl = new_jbutton( "Watch DVD on computer edited realtime", false )
|
111
111
|
@mplayer_edl.on_clicked {
|
112
|
-
do_mplayer_edl
|
112
|
+
do_mplayer_edl
|
113
113
|
}
|
114
114
|
|
115
115
|
@watch_unedited = new_jbutton("Watch a DVD unedited (while grabbing to hard drive)", true)
|
@@ -149,7 +149,7 @@ module SensibleSwing
|
|
149
149
|
old_prefs = File.read(smplayer_prefs_file)
|
150
150
|
new_prefs = old_prefs.gsub(/mplayer_additional_options=.*/, "mplayer_additional_options=-edl #{EdlTempFile}")
|
151
151
|
File.write(smplayer_prefs_file, new_prefs)
|
152
|
-
thread = do_mplayer_edl( "smplayer #{nice_file}"
|
152
|
+
thread = do_mplayer_edl( "smplayer #{nice_file}")
|
153
153
|
Thread.new { # XX do we need this?
|
154
154
|
begin
|
155
155
|
thread.join
|
@@ -189,7 +189,7 @@ module SensibleSwing
|
|
189
189
|
# "dvd_title_track" => "1", # most DVD's use title 1. Yours might not. If it plays anything except the main title, see http://goo.gl/QHLIF
|
190
190
|
# "not edited out stuff" => "",
|
191
191
|
# "closing thoughts" => "still a fairly dark movie",
|
192
|
-
|
192
|
+
# "mplayer_dvd_splits" => ["59:59", "1:04:59"], # find these by playing your dvd with smplayer, and noting where the timing switches [buggedly] back to zero in error--common on many DVD's. Setting it here lets the 'insta play' feature work right.
|
193
193
|
EOL
|
194
194
|
filename = EDL_DIR + "\\" + name.gsub(' ', '_') + '.txt'
|
195
195
|
filename.downcase!
|
@@ -239,21 +239,27 @@ EOL
|
|
239
239
|
|
240
240
|
EdlTempFile = Dir.tmpdir + '/mplayer.temp.edl'
|
241
241
|
|
242
|
-
def do_mplayer_edl
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
242
|
+
def do_mplayer_edl play_this_mplayer = nil, add_secs_end = 0, add_secs_beginning = 0.5
|
243
|
+
drive, dvd_volume_name, md5sum, edl_path, descriptors = choose_dvd_and_edl_for_it
|
244
|
+
descriptors = EdlParser.parse_file edl_path
|
245
|
+
splits = descriptors['mplayer_dvd_splits']
|
246
|
+
if splits == nil
|
247
|
+
show_blocking_message_dialog("warning: delete list does not contain mplayer replay information [mplayer_dvd_splits] so edits past a certain time period won't work (fixable...).")
|
248
|
+
splits = []
|
249
|
+
end
|
250
|
+
splits.map!{|s| EdlParser.translate_string_to_seconds(s) }
|
251
|
+
edl_contents = MplayerEdl.convert_to_edl descriptors, add_secs_end, add_secs_beginning, splits # add a sec to mutes to accomodate for mplayer's oddness...
|
252
|
+
File.write(EdlTempFile, edl_contents)
|
253
|
+
title_track = get_title_track(descriptors)
|
254
|
+
# oh the insanity of the console UI...LODO more user friendly player
|
255
|
+
@popup ||= NonBlockingDialog.new("Running mplayer. To control it, use space for pause.\n
|
256
|
+
Also right and left arrows to seek, F key for full screen, [, ] to control playback speed.
|
257
|
+
q or escape to quit.")
|
258
|
+
# LODO dry up mplayer dvd opts...
|
259
|
+
play_this_mplayer ||= "mplayer dvd://#{title_track}"
|
260
|
+
command = "#{play_this_mplayer} -nocache -alang en -sid 1000 -edl #{File.expand_path EdlTempFile} -dvd-device #{drive}"
|
261
|
+
p command
|
262
|
+
Thread.new { system_blocking command; @popup.dispose }
|
257
263
|
end
|
258
264
|
|
259
265
|
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
|
@@ -369,8 +375,8 @@ EOL
|
|
369
375
|
start_time = JOptionPane.showInputDialog(message, default)
|
370
376
|
end
|
371
377
|
|
372
|
-
def parse_edl path
|
373
|
-
EdlParser.parse_file path
|
378
|
+
def parse_edl path
|
379
|
+
EdlParser.parse_file path
|
374
380
|
end
|
375
381
|
|
376
382
|
def get_freespace path
|
@@ -431,10 +437,13 @@ EOL
|
|
431
437
|
end
|
432
438
|
end
|
433
439
|
|
434
|
-
def do_copy_dvd_to_hard_drive should_prompt_for_start_and_end_times, exit_early_if_fulli_exists = false,
|
440
|
+
def do_copy_dvd_to_hard_drive should_prompt_for_start_and_end_times, exit_early_if_fulli_exists = false, watch_unedited = false
|
435
441
|
drive, dvd_volume_name, md5sum, edit_list_path, descriptors = choose_dvd_and_edl_for_it
|
436
442
|
|
437
|
-
descriptors = parse_edl(edit_list_path
|
443
|
+
descriptors = parse_edl(edit_list_path)
|
444
|
+
if watch_unedited
|
445
|
+
descriptors['mutes'] = descriptors['blank_outs'] = []
|
446
|
+
end
|
438
447
|
|
439
448
|
# LODO allow for spaces in the save_to filename
|
440
449
|
if should_prompt_for_start_and_end_times
|
@@ -464,7 +473,8 @@ EOL
|
|
464
473
|
|
465
474
|
dvd_title_track = get_title_track(descriptors)
|
466
475
|
should_run_mplayer = should_prompt_for_start_and_end_times || exit_early_if_fulli_exists
|
467
|
-
|
476
|
+
require_deletion_entry = true unless watch_unedited
|
477
|
+
generate_and_run_bat_file save_to, edit_list_path, descriptors, drive, dvd_title, start_time, end_time, dvd_title_track, should_run_mplayer, require_deletion_entry
|
468
478
|
[false, fulli] # false means it's running in a background thread :P
|
469
479
|
end
|
470
480
|
|
@@ -474,7 +484,8 @@ EOL
|
|
474
484
|
|
475
485
|
# stubbable :)
|
476
486
|
def get_mencoder_commands descriptors, drive, save_to, start_time, end_time, dvd_title_track, require_deletion_entry
|
477
|
-
|
487
|
+
delete_partials = true unless start_time
|
488
|
+
MencoderWrapper.get_bat_commands descriptors, drive, save_to, start_time, end_time, dvd_title_track, delete_partials, require_deletion_entry # delete partials...
|
478
489
|
end
|
479
490
|
|
480
491
|
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
|
data/lib/edl_parser.rb
CHANGED
@@ -24,8 +24,8 @@ class EdlParser
|
|
24
24
|
parse_string File.read(filename), filename, [], ignore_settings
|
25
25
|
end
|
26
26
|
|
27
|
-
# better eye-ball these before letting people run them, eh?
|
28
|
-
# but I couldn't think of any other way
|
27
|
+
# better eye-ball these before letting people run them, eh? XXXX
|
28
|
+
# but I couldn't think of any other way to parse the files tho
|
29
29
|
def self.parse_string string, filename, ok_categories_array = [], ignore_settings = false
|
30
30
|
string = '{' + string + "\n}"
|
31
31
|
if filename
|
@@ -47,6 +47,7 @@ class EdlParser
|
|
47
47
|
raw
|
48
48
|
end
|
49
49
|
|
50
|
+
# converts "blanks" => ["00:00:00", "00", "reason", "01", "01", "02", "02"] into sane arrays, also filters based on category, though disabled
|
50
51
|
def self.convert_to_timestamp_arrays array, ok_categories_array
|
51
52
|
out = []
|
52
53
|
while(single_element = extract_entry!(array))
|
@@ -76,60 +77,79 @@ class EdlParser
|
|
76
77
|
out
|
77
78
|
end
|
78
79
|
|
80
|
+
def self.get_secs timestamp_string_begin, timestamp_string_end, add_begin, add_end, splits
|
81
|
+
answers = []
|
82
|
+
for type, offset, multiplier in [[timestamp_string_begin, add_begin, -1], [timestamp_string_end, add_end, 1]]
|
83
|
+
original_secs = translate_string_to_seconds(type) + offset
|
84
|
+
# now if splits is 900 and we'are at 909, then we're just 9
|
85
|
+
closest_split_idx = splits.reverse.index{|t| t < original_secs}
|
86
|
+
if closest_split_idx
|
87
|
+
closest_split = splits.reverse[closest_split_idx]
|
88
|
+
# add some extra seconds onto these if they're "past" a split, too
|
89
|
+
original_secs = original_secs - closest_split + multiplier * (splits.length - closest_split_idx)
|
90
|
+
original_secs = [0, original_secs].max # no negatives allowed :)
|
91
|
+
end
|
92
|
+
answers << original_secs
|
93
|
+
end
|
94
|
+
answers
|
95
|
+
end
|
96
|
+
|
79
97
|
# divides up mutes and blanks so that they don't overlap, preferring blanks over mutes
|
80
98
|
# 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_end = 0, add_this_to_mutes_beginning = 0
|
99
|
+
def self.convert_incoming_to_split_sectors incoming, add_this_to_mutes_end = 0, add_this_to_mutes_beginning = 0, splits = []
|
100
|
+
if splits != []
|
101
|
+
# allow it to do all the double checks we later skip, just in case :)
|
102
|
+
self.convert_incoming_to_split_sectors incoming
|
103
|
+
end
|
82
104
|
mutes = incoming["mutes"] || {}
|
83
105
|
blanks = incoming["blank_outs"] || {}
|
84
|
-
mutes = mutes.map{|k, v|
|
85
|
-
blanks = blanks.map{|k, v|
|
86
|
-
|
87
|
-
combined = (mutes+blanks).sort_by{|entry| entry[0,1]}
|
106
|
+
mutes = mutes.map{|k, v| get_secs(k, v, -add_this_to_mutes_beginning, add_this_to_mutes_end, splits) + [:mute]}
|
107
|
+
blanks = blanks.map{|k, v| get_secs(k, v, -add_this_to_mutes_beginning, add_this_to_mutes_end, splits) + [:blank]}
|
108
|
+
p mutes, blanks
|
88
109
|
combined = (mutes+blanks).sort
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
previous[1] = start # make it end when we start...
|
106
|
-
end
|
107
|
-
elsif type == :mute
|
108
|
-
if previous_end > start
|
109
|
-
|
110
|
-
if previous_end >= endy
|
111
|
-
combined[index] = [nil] # null it out...it's a mute subsumed by a blank apparently...
|
112
|
-
if previous_type == :mute
|
113
|
-
raise 'overlapping mute?'
|
114
|
-
end
|
115
|
-
next
|
116
|
-
else
|
117
|
-
# start mine when the last one ended...
|
118
|
-
combined[index] = [previous_end, endy, type]
|
119
|
-
end
|
120
|
-
|
110
|
+
|
111
|
+
previous = nil
|
112
|
+
combined.each_with_index{|current, idx|
|
113
|
+
s,e,t = current
|
114
|
+
if e < s
|
115
|
+
raise SyntaxError.new("detected an end before a start: #{e} < #{s}") if e < s unless splits.length > 0
|
116
|
+
end
|
117
|
+
if previous
|
118
|
+
ps, pe, pt = previous
|
119
|
+
if (s < pe)
|
120
|
+
raise SyntaxError.new("detected an overlap #{[s,e,t].join(' ')} #{previous.join(' ')}") unless splits.length > 0
|
121
|
+
# our start might be within the previous' in which case its their start, with (greater of our, their endig)
|
122
|
+
preferred_end = [e,pe].max
|
123
|
+
preferred_type = [t,pt].detect{|t| t == :blank} || :mute # prefer blank to mute
|
124
|
+
combined[idx-1] = [ps, preferred_end, preferred_type]
|
125
|
+
combined[idx] = nil # allow it to be culled later
|
121
126
|
end
|
122
|
-
|
123
|
-
raise 'unexpected'
|
127
|
+
|
124
128
|
end
|
125
|
-
previous =
|
129
|
+
previous = current
|
126
130
|
}
|
131
|
+
combined.compact
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.translate_string_to_seconds s
|
135
|
+
# might actually already be a float, or int, depending on the yaml
|
136
|
+
# int for 8 => 9 and also for 1:09 => 1:10
|
137
|
+
if s.is_a? Numeric
|
138
|
+
return s.to_f
|
139
|
+
end
|
127
140
|
|
128
|
-
|
129
|
-
|
130
|
-
|
141
|
+
# s is like 1:01:02.0
|
142
|
+
total = 0.0
|
143
|
+
seconds = s.split(":")[-1]
|
144
|
+
total += seconds.to_f
|
145
|
+
minutes = s.split(":")[-2] || "0"
|
146
|
+
total += 60 * minutes.to_i
|
147
|
+
hours = s.split(":")[-3] || "0"
|
148
|
+
total += 60* 60 * hours.to_i
|
149
|
+
total
|
131
150
|
end
|
132
151
|
|
152
|
+
|
133
153
|
end
|
134
154
|
|
135
155
|
# <= 1.8.7 Symbol compat
|
data/lib/mencoder_wrapper.rb
CHANGED
@@ -44,8 +44,8 @@ class MencoderWrapper
|
|
44
44
|
assert dvd_title_track
|
45
45
|
if start_here || end_here
|
46
46
|
raise 'need both' unless end_here && start_here
|
47
|
-
start_here =
|
48
|
-
end_here =
|
47
|
+
start_here = EdlParser.translate_string_to_seconds(start_here)
|
48
|
+
end_here = EdlParser.translate_string_to_seconds(end_here)
|
49
49
|
combined.select!{|start, endy, type| start > start_here && endy < end_here }
|
50
50
|
raise TimingError.new("unable to find deletion entry between #{start_here} and #{end_here}") if require_deletion_entry && combined.length == 0
|
51
51
|
# it's relative now, since we rip from not the beginning
|
data/lib/mplayer_edl.rb
CHANGED
@@ -20,9 +20,9 @@ require_relative 'overlayer'
|
|
20
20
|
require_relative 'edl_parser'
|
21
21
|
|
22
22
|
class MplayerEdl
|
23
|
-
def self.convert_to_edl specs, add_this_many_to_end = 0, add_this_many_to_beginning = 0
|
24
|
-
# simple re-map
|
25
|
-
combined = EdlParser.convert_incoming_to_split_sectors specs, add_this_many_to_end, add_this_many_to_beginning
|
23
|
+
def self.convert_to_edl specs, add_this_many_to_end = 0, add_this_many_to_beginning = 0, splits = []
|
24
|
+
# simple re-map to EDL style output
|
25
|
+
combined = EdlParser.convert_incoming_to_split_sectors specs, add_this_many_to_end, add_this_many_to_beginning, splits
|
26
26
|
out = ''
|
27
27
|
map = {:mute => 1, :blank => 0}
|
28
28
|
for start, endy, type in combined
|
data/lib/overlayer.rb
CHANGED
@@ -105,6 +105,7 @@ class OverLayer
|
|
105
105
|
@start_time = Time.now_f # assume they want to start immediately...
|
106
106
|
end
|
107
107
|
|
108
|
+
# note this is actually deprecated and won't work anymore <sigh> and needs to be updated.
|
108
109
|
def self.translate_yaml raw_yaml
|
109
110
|
begin
|
110
111
|
all = YAML.load(raw_yaml) || {}
|
@@ -120,8 +121,8 @@ class OverLayer
|
|
120
121
|
new = {}
|
121
122
|
maps.each{|start,endy|
|
122
123
|
# both are like 1:02.0
|
123
|
-
start2 = translate_string_to_seconds(start) if start
|
124
|
-
endy2 = translate_string_to_seconds(endy) if endy
|
124
|
+
start2 = EdlParser.translate_string_to_seconds(start) if start
|
125
|
+
endy2 = EdlParser.translate_string_to_seconds(endy) if endy
|
125
126
|
if start2 == 0 || endy2 == 0 || start == nil || endy == nil
|
126
127
|
p 'warning--possible error in the Edit Decision List file some line not parsed! (NB if you want one to start at time 0 please use 0.0001)', start, endy unless $AM_IN_UNIT_TEST
|
127
128
|
# drop this line into the bitbucket...
|
@@ -164,27 +165,10 @@ class OverLayer
|
|
164
165
|
@just_unblanked = false
|
165
166
|
p 'ignoring timestamp update ' + to_this_exact_string_might_be_nil.to_s if $VERBOSE
|
166
167
|
else
|
167
|
-
set_seconds
|
168
|
+
set_seconds EdlParser.translate_string_to_seconds(to_this_exact_string_might_be_nil) + delta if to_this_exact_string_might_be_nil
|
168
169
|
end
|
169
170
|
end
|
170
171
|
|
171
|
-
def self.translate_string_to_seconds s
|
172
|
-
# might actually already be a float, or int, depending on the yaml
|
173
|
-
# int for 8 => 9 and also for 1:09 => 1:10
|
174
|
-
if s.is_a? Numeric
|
175
|
-
return s.to_f
|
176
|
-
end
|
177
|
-
|
178
|
-
# s is like 1:01:02.0
|
179
|
-
total = 0.0
|
180
|
-
seconds = s.split(":")[-1]
|
181
|
-
total += seconds.to_f
|
182
|
-
minutes = s.split(":")[-2] || "0"
|
183
|
-
total += 60 * minutes.to_i
|
184
|
-
hours = s.split(":")[-3] || "0"
|
185
|
-
total += 60* 60 * hours.to_i
|
186
|
-
total
|
187
|
-
end
|
188
172
|
|
189
173
|
# returns seconds it's at currently...
|
190
174
|
def cur_time
|
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.20.
|
8
|
+
s.version = "0.20.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{2011-01-
|
12
|
+
s.date = %q{2011-01-04}
|
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"]
|
data/spec/edl_parser.spec.rb
CHANGED
@@ -89,6 +89,11 @@ describe EdlParser do
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
+
it "should parse mplayer_dvd_splits as floats" do
|
93
|
+
E.parse_string('"mplayer_dvd_splits" => []', 'fakename')['mplayer_dvd_splits'].should == []
|
94
|
+
E.parse_string('"mplayer_dvd_splits" => ["123.5","124.5"]', 'fakename')['mplayer_dvd_splits'].should == ["123.5","124.5"]
|
95
|
+
end
|
96
|
+
|
92
97
|
it "should reject misformatted files" do
|
93
98
|
proc {E.parse_string 'mutes=>["0:33", "0:34"]', 'filename'}.should raise_error(SyntaxError)
|
94
99
|
proc {E.parse_string '"mutes"=>["0:33", "0:34"]', 'filename'}.should_not raise_error
|
@@ -99,12 +104,52 @@ describe EdlParser do
|
|
99
104
|
end
|
100
105
|
|
101
106
|
it "should sort exactly overlapping segments" do
|
102
|
-
|
107
|
+
proc { go({"mutes"=>{105=>145}, "blank_outs"=>{105=>145}})}.should raise_error(SyntaxError)
|
108
|
+
proc { go({"mutes"=>{105=>145}, "blank_outs"=>{110=>130}})}.should raise_error(SyntaxError)
|
109
|
+
proc { go({"mutes"=>{105=>145}, "blank_outs"=>{110=>150}})}.should raise_error(SyntaxError)
|
103
110
|
end
|
104
111
|
|
105
112
|
it "should add to both ends" do
|
106
|
-
|
107
|
-
|
113
|
+
go({"mutes"=>{105=>145}}, 1).should == [[105.0, 146.0, :mute]]
|
114
|
+
go({"mutes"=>{105=>145}}, 1,1).should == [[104.0, 146.0, :mute]]
|
115
|
+
end
|
116
|
+
|
117
|
+
def go *args
|
118
|
+
EdlParser.convert_incoming_to_split_sectors *args
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should raise for end before beginning" do
|
122
|
+
proc{ go({"mutes"=>{105=>104.9}})}.should raise_error(SyntaxError)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should allow for splits in its parseage" do
|
126
|
+
go({ "mutes"=>{5=>6,105=>106}, "blank_outs" => {110 => 111} }, 0, 0, [103]).should ==
|
127
|
+
[[1.0, 4.0, :mute], [5.0, 6.0, :mute], [6.0, 9.0, :blank]]
|
108
128
|
end
|
109
129
|
|
110
|
-
|
130
|
+
it "should raise on poor overlap" do
|
131
|
+
proc{go({ "mutes"=>{5=>10, 6=>7}}, 0, 0, [1000])}.should raise_error(/overlap/i)
|
132
|
+
end
|
133
|
+
|
134
|
+
# I put down it at 10:00 it's at 10:00.5
|
135
|
+
# so...postludingers should be...too early now?
|
136
|
+
# change when complaints come in :P
|
137
|
+
it "should take the greater of the end and beginning on combined splits and greater of the blank versus mute" do
|
138
|
+
# so if I have a very long mute with a mute in the middle, it should turn into a very long mute
|
139
|
+
go({ "mutes"=>{5=>10, 103=>107}}, 0, 0, [100]).should == [[2.0, 10.0, :mute]]
|
140
|
+
go({ "mutes"=>{5=>10, 103=>110}}, 0, 0, [100]).should == [[2.0, 11.0, :mute]]
|
141
|
+
go({ "mutes"=>{5=>15, 103=>110}}, 0, 0, [100]).should == [[2.0, 15.0, :mute]]
|
142
|
+
go({ "mutes"=>{5=>10, 103=>111}}, 0, 0, [100]).should == [[2.0, 12.0, :mute]]
|
143
|
+
# now throw in blanks to the mix...
|
144
|
+
go({ "mutes"=>{5=>10}, "blank_outs" => {103=>110}}, 0, 0, [100]).should == [[2.0, 11.0, :blank]]
|
145
|
+
go({ "blank_outs"=>{5=>10}, "mutes" => {103=>110}}, 0, 0, [100]).should == [[2.0, 11.0, :blank]]
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should accomodate well for multiples, and zero" do
|
149
|
+
go({ "mutes"=>{5=>10, 75 => 76, 101 => 102}}, 0, 0, [50, 100]).should ==
|
150
|
+
[[0.0, 4.0, :mute], [5.0, 10.0, :mute], [24.0, 27.0, :mute]]
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should handle edge cases, like where an entry overlaps the divider, or the added stuff causes it to"
|
154
|
+
|
155
|
+
end
|