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 CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.19.1 ==
2
+
3
+ Clarify buttons' meanings, layout (add one), fix some bugs in create mode, like it not re-loading edited files.
4
+ Can optionally watch unedited.
5
+
1
6
  == 0.19.0 ==
2
7
 
3
8
  Add working EDL playback with mplayer, cleanup interfaces.
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 edit lists (i.e. Edit Decision Lists) to DVD's you own [2].
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] (VLC Media Player, Mplayer/mencoder, ffmpeg et al)
8
- to accomplish the editing for you. Then you can sit back and relax as you watch a "sanitized"
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 section, below).
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 an edited copy of your DVD, note that it will take about one and a half times
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 Edit Lists, or modifying previously existing ones ==
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 edit decision lists, per DVD.
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 an edit decision is past end of DVD, or
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
- system("#{Gem.ruby} -S gem push #{Dir['pkg/*.gem'][-1]}")
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
- make sure release has right .bat files
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.0
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 only_on_create_mode
53
- if ARGV.index("--create-mode") || ARGV.index("-c")
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
- path = RubyWhich.new.which('smplayer')
130
- path2 = RubyWhich.new.which('mplayer')
131
- if(path.length == 0 || path2.length == 0)
132
- # this one has its own license...
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
- success_no_run, wrote_to_here_fulli = do_copy_dvd_to_hard_drive true
148
- on_success = proc { |file|
149
- system_non_blocking("smplayer #{file}")
150
- }
151
- if success_no_run
152
- on_success.call
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/Edit a pre-existing DVD Edit List", true)
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 Edit Decision List for a DVD", true)
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 Edit Decision List File"
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 an edit decision 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
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
- @rem taskkill /f /im mencoder.exe
6
+ @taskkill /f /im mencoder.exe
data/how_to_create.txt CHANGED
@@ -1,16 +1,16 @@
1
- You create an edit decision list for sensible cinema to use against whatever you want.
1
+ You create a delete list for sensible cinema to use against whatever you want.
2
2
 
3
- An Edit Decision List looks something like this:
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) somewhere,
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 in create mode
13
- insert DVD, click "create new edit list" button
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 edit lists per DVD. One that takes out swearing, sex, and gruesome violence, and another
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
@@ -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 'vlc_programmer'
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 = VLCProgrammer.convert_incoming_to_split_sectors these_settings
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
- combined = VLCProgrammer.convert_incoming_to_split_sectors specs, add_this_many_to_end
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
@@ -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
 
@@ -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.0"
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-18}
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",
@@ -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'}.should_not raise_error(/unable/)
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
- it "should prompt if two EDL's match a DVD title" do
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
- MainWindow.const_set(:EDL_DIR, 'temp')
65
- FileUtils.rm_rf 'temp'
66
- Dir.mkdir 'temp'
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[-4].should match(/abc/)
98
+ args[-5].should match(/abc/)
93
99
  @args = args
94
- 'sleep 0.1'
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[-3].should == nil
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[-1].should == 1
166
- @args[-2].should == "01:00"
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
- @subject.instance_variable_get(:@preview_section).simulate_click
173
- @args[-1].should == 1
174
- @args[-2].should == "01:00"
175
- @subject.background_thread.join
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 the .done file exists, it should directly call smplayer" do
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 # scary timing spec!
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.6 1")
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
 
@@ -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
- #59:16
5
- #59:22
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
- "1:01:35", "1:01:45"
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
- - 0
9
- version: 0.19.0
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-18 00:00:00 -07:00
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