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 CHANGED
@@ -2,18 +2,24 @@
2
2
 
3
3
  == up next release ==
4
4
 
5
- edl straight DVD replay: work HP
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
- the 0.5 offset only is applying to mutes currently [fix]
13
- also note that the beginning offset is wrong-o [?]
14
- "watch edited while grabbing"
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.0
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 (not always be accurate)", false )
110
+ @mplayer_edl = new_jbutton( "Watch DVD on computer edited realtime", false )
111
111
  @mplayer_edl.on_clicked {
112
- do_mplayer_edl nil, 0, 0.5
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}", 0, 0.5)
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 play_this_start, add_secs_end, add_secs_beginning
243
- drive, dvd_volume_name, md5sum, edl_path, descriptors = choose_dvd_and_edl_for_it
244
- descriptors = EdlParser.parse_file edl_path
245
- edl_contents = MplayerEdl.convert_to_edl descriptors, add_secs_end, add_secs_beginning # add a sec to mutes to accomodate for mplayer's oddness...
246
- File.write(EdlTempFile, edl_contents)
247
- title_track = get_title_track(descriptors)
248
- # oh the insanity of the console UI...LODO more user friendly player
249
- @popup ||= NonBlockingDialog.new("Running mplayer. To control it, use space for pause.\n
250
- Also right and left arrows to seek, F key for full screen, [, ] to control playback speed.
251
- q to quit.")
252
- # LODO dry up mplayer dvd opts...
253
- play_this_start ||= "mplayer dvd://#{title_track}"
254
- command = "#{play_this_start} -nocache -alang en -sid 1000 -edl #{File.expand_path EdlTempFile} -dvd-device #{drive}"
255
- p command
256
- Thread.new { system_blocking command; @popup.dispose }
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, ignore_settings = false
373
- EdlParser.parse_file path, ignore_settings
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, ignore_settings = 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, ignore_settings)
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
- generate_and_run_bat_file save_to, edit_list_path, descriptors, drive, dvd_title, start_time, end_time, dvd_title_track, should_run_mplayer, !ignore_settings
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
- MencoderWrapper.get_bat_commands descriptors, drive, save_to, start_time, end_time, dvd_title_track, true, require_deletion_entry # delete partials...
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| [OverLayer.translate_string_to_seconds(k) - add_this_to_mutes_beginning, OverLayer.translate_string_to_seconds(v) + add_this_to_mutes_end, :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_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
- combined.each{|s, e, t|
91
- puts 'warning--detected an end before a start' if e < s
92
- }
93
-
94
- # VLCProgrammer.convert_to_full_xspf({ "mutes" => {5=> 7}, "blank_outs" => {6=>7} } )
95
- # should mute 5-6, skip 6-7
96
- previous = combined[0]
97
- combined.each_with_index{|(start, endy, type), index|
98
- next if index == 0 # nothing to do there..
99
- previous_end = previous[1]
100
- previous_type = previous[2]
101
- previous_start = previous[0]
102
- if type == :blank
103
- raise 'no overlap like that allowed as of yet' unless previous_end <= endy
104
- if previous_type == :mute && previous_end > start
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
- else
123
- raise 'unexpected'
127
+
124
128
  end
125
- previous = combined[index]
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
- combined.select{|start, endy, type|
129
- (start != nil) && (endy > start) # ignore mutes wholly contained within blanks...
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
@@ -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 = OverLayer.translate_string_to_seconds(start_here)
48
- end_here = OverLayer.translate_string_to_seconds(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 OverLayer.translate_string_to_seconds(to_this_exact_string_might_be_nil) + delta if to_this_exact_string_might_be_nil
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
@@ -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.0"
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-03}
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"]
@@ -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
- EdlParser.convert_incoming_to_split_sectors({"mutes"=>{105=>145}, "blank_outs"=>{105=>145}}).should == [[105.0, 145.0, :blank]]
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
- EdlParser.convert_incoming_to_split_sectors({"mutes"=>{105=>145}}, 1).should == [[105.0, 146.0, :mute]]
107
- EdlParser.convert_incoming_to_split_sectors({"mutes"=>{105=>145}}, 1,1).should == [[104.0, 146.0, :mute]]
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
- end
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