Class: SensibleSwing::MainWindow

Inherits:
JFrame
  • Object
show all
Includes:
SwingHelpers
Defined in:
lib/gui/base.rb,
lib/gui/create.rb,
lib/gui/normal.rb,
lib/gui/upconvert.rb,
lib/gui/create-file.rb,
lib/gui/dependencies.rb

Constant Summary collapse

LocalStorage =
Storage.new("sensible_cinema_storage_#{VERSION}")
SMPlayerIniFile =
File.expand_path("~/.smplayer_sensible_cinema/smplayer.ini")
LocalModifiedMplayer =
File.expand_path "vendor/cache/mplayer_edl/mplayer.exe"
EdlTempFile =

stay 8.3 friendly :)

Dir.tmpdir + '/mplayer.temp.edl'
EdlFilesChosen =

allow for switching tapes but still cache EDL loc. :P

{}
NonDvd =

we need it for convenience, say you want to go through your indexed vids and convert them all?

'non dvd has no dvdid'
UpConvertKey =
'upconvert_setting'
UpConvertKeyExtra =
'upconvert_setting_extra'
UpConvertEnglish =
'upconvert_english_name'
ScreenMultipleFactor =
'screen_multiples'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(start_visible = true, args = ARGV) ⇒ MainWindow

lodo not optionals



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/gui/base.rb', line 89

def initialize start_visible = true, args = ARGV # lodo not optionals
  super "Sensible-Cinema #{VERSION} (GPL)"
 @args = args # save them away so this works with sub-child-windows
  force_accept_license_first # in other file :P
  setDefaultCloseOperation JFrame::EXIT_ON_CLOSE # closes the whole app when they hit X ...
  @panel = JPanel.new
  @buttons = []
  @panel.set_layout nil
  add @panel # why can't I just slap these down? panel? huh?
  @starting_button_y = 40
  @button_width = 400      
  
  add_text_line "Welcome to Sensible Cinema!"
  @starting_button_y += 10 # kinder ugly...
  add_text_line "      Rest mouse over buttons for \"help\" type descriptions (tooltips)."
  @current_dvds_line1 = add_text_line "Checking present DVD's..."
  @current_dvds_line2 = add_text_line ""
  @callbacks_for_dvd_edl_present = []
  DriveInfo.create_looping_drive_cacher
  DriveInfo.add_notify_on_changed_disks { update_currently_inserted_dvd_list }      
	  icon_filename = __DIR__ + "/../../vendor/profs.png"
	  raise unless File.exist? icon_filename # it doesn't check this for us?
  setIconImage(ImageIcon.new(icon_filename).getImage())
  check_for_various_dependencies
	  LocalStorage.set_once('init_preferences_once') {
 show_blocking_message_dialog "lets setup some preferences once..."
 set_individual_preferences
	  }
  set_visible start_visible
end

Instance Attribute Details

#background_threadObject

Returns the value of attribute background_thread.



619
620
621
# File 'lib/gui/base.rb', line 619

def background_thread
  @background_thread
end

#buttonsObject

Returns the value of attribute buttons.



619
620
621
# File 'lib/gui/base.rb', line 619

def buttons
  @buttons
end

#parentObject

Returns the value of attribute parent.



24
25
26
# File 'lib/gui/normal.rb', line 24

def parent
  @parent
end

#upconv_lineObject

Returns the value of attribute upconv_line.



24
25
26
# File 'lib/gui/normal.rb', line 24

def upconv_line
  @upconv_line
end

Class Method Details

.download(full_url, to_here) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/gui/dependencies.rb', line 25

def self.download full_url, to_here
  require 'open-uri'
  require 'openssl'
  eval("OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE") if full_url =~ /https/
  keep_going_bg_thread = true
  print 'downloading'
  Thread.new { while keep_going_bg_thread; print '.'; sleep 1; end}
  writeOut = open(to_here, "wb")
  writeOut.write(open(full_url).read)
  writeOut.close
  keep_going_bg_thread = false
  puts 'done!'
end

.download_to_string(full_url) ⇒ Object



39
40
41
42
43
44
45
46
# File 'lib/gui/dependencies.rb', line 39

def self.download_to_string full_url
   require 'tempfile'
   to = Tempfile.new 'abc'
   download(full_url, to.path)
   out = File.binread(to.path)
   to.delete
   out
end

Instance Method Details

#add_callback_for_dvd_edl_present(&block) ⇒ Object



120
121
122
123
124
# File 'lib/gui/base.rb', line 120

def add_callback_for_dvd_edl_present &block
  raise unless block
  @callbacks_for_dvd_edl_present << block
  update_currently_inserted_dvd_list # updates them :P
end

#add_change_upconvert_buttonsObject



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/gui/upconvert.rb', line 84

def add_change_upconvert_buttons
  raise 'should have already been set for us' unless LocalStorage[ScreenMultipleFactor]
  @medium_dvd = new_jbutton("Set upconvert options to DVD-style video") {
    luma_spatial = 0
    chroma_spatial = 1
    luma_tmp = 4
    chroma_tmp = 4
    LocalStorage[UpConvertKey] = "hqdn3d=%s:%s:%s:%s,scale=SCREEN_X:-10:0:0:2" % [luma_spatial, chroma_spatial, luma_tmp, chroma_tmp]
    # hqdn3d[=luma_spatial:chroma_spatial:luma_tmp:chroma_tmp]
    LocalStorage[UpConvertKeyExtra] = "-sws 9 -ssf ls=75.0 -ssf cs=7.0"
    LocalStorage[UpConvertEnglish] = "DVD"
    display_current_upconvert_setting_and_close_window
  }
  high_compression = new_jbutton("Set upconvert options to high compressed video file playback") {
    # -autoq 6 -vf pp [?]
    LocalStorage[UpConvertEnglish] = "high compressed"
    LocalStorage[UpConvertKey] = "hqdn3d=0:1:4:4,pp=hb:y/vb:y,scale=SCREEN_X:-10:0:0:3" # pp should be after hqdn3d I think... and hqdn3d should be before scale...
    LocalStorage[UpConvertKeyExtra] = "-sws 9 -ssf ls=75.0 -ssf cs=25.0"
    display_current_upconvert_setting_and_close_window
    # -Processing method: mplayer with accurate deblocking ???
  }
  new_jbutton("Set upconvert options to experimental screen-upconverting playback") {
    LocalStorage[UpConvertKey] = "scale=SCREEN_X:-10:0:0:3" # no hqdn3d
    LocalStorage[UpConvertKeyExtra] = "-sws 9 -ssf ls=75.0 -ssf cs=25.0"
    LocalStorage[UpConvertEnglish] = "experimental screenupconversion"
    display_current_upconvert_setting_and_close_window
  }
  
  new_jbutton("Set upconvert options to whatever you want [like -sws 9 -ssf ls=100.0 -- for advanced users]") {
    new_settings = get_user_input("you can set -vf settings, and then other settings. What would you like your -vf settings to be?")
    LocalStorage[UpConvertKey] = new_settings
    other_settings = get_user_input("other settings you'd like to also have add:")
    LocalStorage[UpConvertKeyExtra] = other_settings
    LocalStorage[UpConvertEnglish] = "personalized: -vf #{new_settings}, #{other_settings}"      
  }
  
  # TODO tooltip from docu here +- this into tooltip
  # TODO "click here" link for more docu [?]
  add_text_line "Multiple factor screen widths"
  add_text_line "   (higher might be better, uses more cpu)." 
  add_text_line "   If mplayer just dies or displays only a black or white screen then lower this setting, it is too high."
  slider = JSlider.new
  slider.setBorder(BorderFactory.createTitledBorder("Screen resolution multiple"));
  
  # I want tick for 1x, 1.5x, 2x, 2.5x, 3x
  # so let's do marker values of 10 -> 30, since it requires integers...
  
  labelTable = java.util.Hashtable.new
  i = java.lang.Integer
  l = JLabel
  
  # allow for 0.75 too, if you have a large monitor, slower cpu...
  local_minimum = (720.0/get_current_max_width_resolution)*100 # allows 1024 to use upscaling to 860, but we warn when they do this
  label_minimum = nil
  (0..300).step(25) do |n|
    if n > local_minimum
      label_minimum ||= n
      if (n % 100 == 0)
        labelTable.put(i.new(n), l.new("#{n/100}x")) # 1x
      elsif n == label_minimum # just for the bottom label, rest too chatty
        labelTable.put(i.new(n), l.new("#{n/100.0}x")) # 1.5x
      end
    end
  end
  slider.setLabelTable( labelTable )
  
  slider.maximum=300
  slider.minimum=label_minimum
  slider.setMajorTickSpacing(100) 
  slider.setMinorTickSpacing(25) 
  slider.setPaintTicks(true)
  slider.setPaintLabels(true)    
  slider.snap_to_ticks=true
  
  slider.set_value LocalStorage[ScreenMultipleFactor] * 100
  
  slider.add_change_listener { |event|
    if !slider.value_is_adjusting
      # they released their hold on it...
      old_value = LocalStorage[ScreenMultipleFactor]
      new_value = slider.value/100.0
      LocalStorage[ScreenMultipleFactor] = new_value
      if new_value != old_value
        if slider.value == label_minimum
          show_blocking_message_dialog "Setting it too low like that might make it not do much upconverting (DVD's, are 720px, you're setting it to upconvert to #{new_value * get_current_max_width_resolution})"
        end
        display_current_upconvert_setting_and_close_window
      end
    end
  }
  slider.set_bounds(44, @starting_button_y, @button_width, 66)
  2.times {increment_button_location}
  @panel.add(slider)
  
  increment_button_location
  
  @none = new_jbutton("Reset upconvert options to none (no upconversion)")
  @none.tool_tip = "Having no upconvert options is reasonably good, might use directx for scaling, nice for slow cpu's"
  @none.on_clicked {
    LocalStorage[UpConvertKey] = nil
    LocalStorage[UpConvertKeyExtra] = nil
    LocalStorage[UpConvertEnglish] = nil
    display_current_upconvert_setting_and_close_window
  }
  
  @generate_images = new_jbutton("Test current configuration by writing some images from playing a video file") do
    popup = warn_if_no_upconvert_options_currently_selected
    filename_mpg = new_existing_file_selector_and_select_file( "pick movie file (like moviename.mpg)")
    
    output_dir = get_same_drive_friendly_clean_temp_dir 'temp_upscaled_video_out'
    output_command = '-ss 2:44 -frames 300 -vo png:outdir="' + File.strip_drive_windows(output_dir) + '"'
    output_command += " -noframedrop" # don't want them to skip frames on cpu's without enough power to keep up
    thread = play_smplayer_edl_non_blocking [filename_mpg, nil], [output_command], true
    when_thread_done(thread) { popup.dispose; show_in_explorer(output_dir) }
  end
  @generate_images.tool_tip = "This creates a folder with images upconverted from some DVD or file, so you can tweak settings and compare." # TODO more tooltips

  @generate_screen_cast = new_jbutton("Test current configuration by watching video file and recording screen") do
    popup = warn_if_no_upconvert_options_currently_selected
    filename_mpg = new_existing_file_selector_and_select_file( "pick movie file (like moviename.mpg)")
    output_dir = get_same_drive_friendly_clean_temp_dir 'temp_screencast_dir'
    thread1 = play_smplayer_edl_non_blocking [filename_mpg, nil], [" -ss 2:44 -endpos 11"]
    # screen capture for 10s
    fps_to_grab = 5
    thread2 = Thread.new {  c = %!ffmpeg -f dshow -i video="screen-capture-recorder" -r #{fps_to_grab} -vframes #{fps_to_grab*10} -y #{File.strip_drive_windows(output_dir)}/%d.png!; system_blocking c }
    thread2.join
    show_blocking_message_dialog "ffmpeg done, close mplayer now!"
    thread1.join
    popup.dispose # just in case :P
    show_in_explorer(output_dir)
  end


end

#add_change_upconvert_options_buttonObject



52
53
54
55
56
57
58
# File 'lib/gui/upconvert.rb', line 52

def add_change_upconvert_options_button
  @show_upconvert_options = new_jbutton("Tweak Playback Upconversion Quality Settings") do
    upconvert_window = new_child_window
    upconvert_window.add_change_upconvert_buttons
  end
  @show_upconvert_options.tool_tip= "Allows you to set your upconvert options.\nUpconverting attempts to playback your movie with higher quality on high resolution monitors."
end

#add_open_documentation_buttonObject



114
115
116
117
118
# File 'lib/gui/normal.rb', line 114

def add_open_documentation_button
  @open_help_file = new_jbutton("View Sensible Cinema Documentation") do
    show_in_explorer __DIR__ + "/../../documentation"
  end
end

#add_options_that_use_local_filesObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/gui/create-file.rb', line 5

def add_options_that_use_local_files
  force_accept_file_style_license
 check_for_file_manipulation_dependencies
  add_text_line 'These are Create Options that operate on a file:'

  @preview_section = new_jbutton( "Preview a certain time frame (edited)" )
  @preview_section.tool_tip = <<-EOL
    This allows you to preview an edit easily.
    It is the equivalent of saying \"watch this file edited from exactly minute x second y to minute z second q"
    Typically if you want to test an edit, you can start a few seconds before, and end a few seconds after it, to test it precisely.
  EOL
  @preview_section.on_clicked {
    do_create_edited_copy_via_file true
  }
  
  @preview_section_unedited = new_jbutton("Preview a certain time frame (unedited)" )
  @preview_section.tool_tip = "Allows you to view a certain time frame unedited (ex: 10:00 to 10:05), so you can narrow down to pinpoint where questionable scenes are, etc. This is the only way to view a specific scene if there are not cuts within that scene yet."
  @preview_section_unedited.on_clicked {
    do_create_edited_copy_via_file true, false, true
  }

  @rerun_preview = new_jbutton( "Re-run most recently watched previewed time frame" )
  @rerun_preview.tool_tip = "This will re-run the preview that you most recently performed.  Great for checking to see if you last edits were successful or not."
  @rerun_preview.on_clicked {
    repeat_last_copy_dvd_to_hard_drive
  }
  
  # I think this is still useful...
  @fast_preview = new_jbutton("fast preview EDL from fulli file (smplayer EDL)")
  @fast_preview.tool_tip = <<-EOL
    Plays smplayer on a file with an EDL.
    This gives you a rough estimate to see if your edits are accurate, and is really fast to seek, etc.
    This is useful because you can't use mplayer on a DVD for accurate timestamps if it has any 
    timestamp splits in it [because some DVD's are buggy]
  EOL
  @fast_preview.on_clicked {
    success, wrote_to_here_fulli = do_create_edited_copy_via_file false, true
    sleep 0.5 # lodo take out ???
    background_thread.join if background_thread # let it write out the original fulli, if necessary [?]
    nice_file = wrote_to_here_fulli
    run_smplayer_blocking nice_file, nil, "-edl #{EdlTempFile}", false, true, false, nil
  }
end

#add_play_upconvert_buttonsObject



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/gui/upconvert.rb', line 6

def add_play_upconvert_buttons

  @watch_file_upconvert = new_jbutton( "Watch a movie file upconverted (unedited)") do
    popup = warn_if_no_upconvert_options_currently_selected
    filename_mpg = new_existing_file_selector_and_select_file( "pick movie file (like moviename.mpg)")
    thread = play_smplayer_edl_non_blocking [filename_mpg, nil]
    when_thread_done(thread) { popup.dispose }
  end
  @watch_file_upconvert.tool_tip= "This plays back a movie file, like moviefile.mpg, or moviename.vob using your current upconverter settings.\nTo playback a file edited upconverted, set upconvert options here first, then run them using sensible cinema main--it will automatically use your new upconverting options.\n" # LODO
  
  @watch_dvd_upconvert = new_jbutton( "Watch a DVD upconverted (unedited)") do
    popup = warn_if_no_upconvert_options_currently_selected
    thread = play_dvd_smplayer_unedited false
    when_thread_done(thread) { popup.dispose }
  end
  @watch_dvd_upconvert.tool_tip = "Plays back the currently inserted DVD, using your current upconverter settings.\nIf it fails (dies immediately, blank screen, etc.), try setting upconvert options to a smaller screen resolution multiple.\nOr try playing the DVD with VLC first, then it might work.\nTo playback a DVD edited upconverted, set upconvert options here first, then run them using sensible cinema main--it will automatically use your new upconverting options."
  
  @watch_online = new_jbutton( "Watch upconverted online player, like netflix instant") do
    show_blocking_message_dialog("sorry not mac compat. yet") and raise unless OS.doze?
    answer = JOptionPane.show_select_buttons_prompt("Warning: you must have the screen capture device installed (install MSVC 2010 runtime x86 first), and also configured using its setup utility, and avisynth installed.", :yes => 'take me to its website', :no => 'I already and configured it, let me at it!')
    if answer == :yes
       SwingHelpers.open_url_to_view_it_non_blocking "https://github.com/rdp/screen-capture-recorder-to-video-windows-free"
       raise 'install it'
    end
    run_smplayer_non_blocking "upconvert_from_screen/upconvert_from_screen_me2.avs", nil, '', force_mplayer = true, true, false, nil
  end
  
  add_text_line ''
  @upconv_line = add_text_line ''
  change_upconvert_line_to_current
  
  add_change_upconvert_options_button
  if !upconvert_set_to_anything?
    show_blocking_message_dialog 'please configure your upconvert settings first'
    @show_upconvert_options.simulate_click # make them choose one
  end
  add_text_line ''
  
end

#add_text_line(line) ⇒ Object



194
195
196
197
198
199
200
201
202
# File 'lib/gui/base.rb', line 194

def add_text_line line
  jlabel = JLabel.new line
  happy = Font.new("Tahoma", Font::PLAIN, 11)
  jlabel.setFont(happy)
  jlabel.set_bounds(44,@starting_button_y ,460,14)
  @panel.add jlabel
  increment_button_location 18
  jlabel
end

#assert_confirmed_dialog(returned, license_url_should_also_be_embedded_by_you_in_message) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/gui/dependencies.rb', line 156

def assert_confirmed_dialog returned, license_url_should_also_be_embedded_by_you_in_message
  # :yes is "view license", :no is "accept", :cancel
  if returned == :yes
    if license_url_should_also_be_embedded_by_you_in_message
      SwingHelpers.open_url_to_view_it_non_blocking license_url_should_also_be_embedded_by_you_in_message
      puts "Please restart after reading license agreement, to be able to then accept it."
    else
      puts 'dialog assertion failed'
    end
    System.exit 0
  elsif returned == :cancel
    p 'license not accepted...exiting'
    System.exit 1
  elsif returned == :exited
    p 'license exited early...exiting'
    System.exit 1
  elsif returned == :no
    # ok
  else
    raise 'unknown?'
  end
end

#assert_ownership_dialogObject



132
133
134
135
136
137
138
# File 'lib/gui/dependencies.rb', line 132

def assert_ownership_dialog 
  force_accept_file_style_license
  message = "Do you certify you own the DVD this came of and have it in your possession, if necessary in your legal jurisdiction?"
  title = "Verify ownership"
  returned = JOptionPane.show_select_buttons_prompt(message, {:yes => "no", :no => "yes"})
  assert_confirmed_dialog returned, nil
end

#begin_buffer_preferenceObject

MplayerBeginingBuffer = 1.0

MplayerEndBuffer = 0.0


489
490
491
# File 'lib/gui/base.rb', line 489

def begin_buffer_preference
 LocalStorage['mplayer_beginning_buffer']
end

#calculate_dvd_start_offset(title, drive) ⇒ Object



400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/gui/create.rb', line 400

def calculate_dvd_start_offset title, drive
  popup = show_non_blocking_message_dialog "calculating start info for title #{title}..." # must be non blocking so the command can run :P
  command = "mplayer -benchmark -frames 35  -osd-verbose -osdlevel 2 -vo null -nosound dvdnav://#{title} -nocache -dvd-device #{drive}  2>&1"
  puts command
  out = `#{command}`
  #search for V:  0.37
  popup.close
  outs = {}
	  old_mpeg = 0
  out.each_line{|l|
    if l =~  /V:\s+([\d\.]+)/
      outs[:mpeg_start_offset] ||= $1.to_f
    end
   float = /\d+\.\d+/
  if l =~ /last NAV packet was (#{float}), mpeg at (#{float})/
      nav = $1.to_f
      mpeg = $2.to_f
      if !outs[:dvd_nav_packet_offset] && nav > 0.0 # like 0.4
 if mpeg < nav
   # case there is an MPEG split before the second NAV packet [ratatouille, hp]
   p mpeg, nav, old_mpeg
   assert old_mpeg > 0.3
mpeg = old_mpeg + mpeg - 0.033367 # assume 30 fps, and that this is the second frame since it occurred, since the first one we apparently display "weird suddenly we're not a dvd?"
show_blocking_message_dialog "this dvd has some weird timing stuff at the start, attempting to accomodate...please report..."
 end
       outs[:dvd_nav_packet_offset] = [nav, mpeg] # like [0.4, 0.6] or the like
        else
 old_mpeg = mpeg # ratatouile weirdness...
 end
  	  end
  }
  show_blocking_message_dialog "unable to calculate DVD start time from #{command}?" unless outs.length == 2
  outs
end

#change_upconvert_line_to_currentObject



69
70
71
72
73
74
75
76
77
# File 'lib/gui/upconvert.rb', line 69

def change_upconvert_line_to_current
  current = get_current_upconvert_as_phrase
  if @upconv_line
    @upconv_line.set_text current
  end
  if @parent && @parent.upconv_line
    @parent.upconv_line.set_text current
  end # LODO I think the child also wants a status line..
end

#check_for_exe(windows_full_loc, unix_name) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/gui/dependencies.rb', line 72

def check_for_exe windows_full_loc, unix_name
  # in windows, that exe *at that location* must exist...
  if OS.windows?
    File.exist?(windows_full_loc)
  else
    require 'lib/check_installed_mac.rb'
    if !CheckInstalledMac.check_for_installed(unix_name)
      exit 1 # it'll have already displayed a message...
    else
      true
    end
  end
end

#check_for_file_manipulation_dependenciesObject



86
87
88
89
90
91
92
93
94
# File 'lib/gui/dependencies.rb', line 86

def check_for_file_manipulation_dependencies	
if !check_for_exe('vendor/cache/mencoder/mencoder.exe', 'mencoder') # both use it now, since we have to use our own mplayer.exe for now...
    require_blocking_license_accept_dialog 'mplayer', 'gplv2', 'http://www.gnu.org/licenses/gpl-2.0.html', "Appears that you need to install a dependency: mplayer with mencoder."
    download_zip_file_and_extract "Mplayer/mencoder (6MB)", "http://sourceforge.net/projects/mplayer-win32/files/MPlayer%20and%20MEncoder/revision%2034118/MPlayer-rtm-svn-34118.7z", "mencoder"
    old = File.binread 'vendor/cache/mencoder/mplayer.exe'
    old.gsub! "V:%6.1f", "V:%6.2f" # better precision! though I don't use that for playing anymore :)
    File.binwrite('vendor/cache/mencoder/mplayer.exe', old)
  end
end

#check_for_various_dependenciesObject



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/gui/dependencies.rb', line 96

def check_for_various_dependencies            
  if OS.doze? && !check_for_exe('vendor/cache/mplayer_edl/mplayer.exe', nil)
    require_blocking_license_accept_dialog 'Mplayer-EDL', 'gplv2', 'http://www.gnu.org/licenses/gpl-2.0.html', "Appears that you need to install a dependency: mplayer EDL "
    FileUtils.mkdir_p 'vendor/cache/mplayer_edl'
    puts 'downloading mplayer edl [12 MB]'
    MainWindow.download('http://sourceforge.net/projects/mplayer-edl/files/0.4/mplayer.exe', 'vendor/cache/mplayer_edl/mplayer.exe')
		config_dir = File.expand_path('~/mplayer')
		FileUtils.mkdir(config_dir) unless File.directory?(config_dir)
		FileUtils.cp('vendor/subfont.ttf', config_dir) # TODO mac
  end

  # runtime dependencies, at least as of today...
  ffmpeg_exe_loc = File.expand_path('vendor/cache/ffmpeg/ffmpeg.exe') # I think file basd normal needs ffmpeg
  if !check_for_exe(ffmpeg_exe_loc, 'ffmpeg')
    require_blocking_license_accept_dialog 'ffmpeg', 'gplv2', 'http://www.gnu.org/licenses/gpl-2.0.html', "Appears that you need to install a dependency: ffmpeg."
    download_zip_file_and_extract "ffmpeg (5MB)", "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-git-335bbe4-win32-static.7z", "ffmpeg"
  end
  if OS.mac?
    check_for_exe("mplayer", "mplayer") # mencoder and mplayer are separate for mac... [this checks for mac's mplayerx, too]
  else      
    path = RubyWhich.new.which('smplayer')
    if(path.length == 0)
      # this one has its own installer...
    require_blocking_license_accept_dialog 'Smplayer', 'gplv2', 'http://www.gnu.org/licenses/gpl-2.0.html', "Appears that you need to install a dependency: smplayer."
 		  save_to_dir = SwingHelpers.new_existing_dir_chooser_and_go 'pick dir to save smplayer exe installer to:'
    save_to_file =  "#{save_to_dir}/smplayer-0.6.9-win32.exe"
		  puts "downloading smplayer.exe [14MB] to #{save_to_file}"
      MainWindow.download "http://sourceforge.net/projects/smplayer/files/SMPlayer/0.6.9/smplayer-0.6.9-win32.exe", save_to_file
    show_blocking_message_dialog "Run this file to install it (ok to reveal): smplayer-0.6.9-win32.exe"
		  show_in_explorer save_to_file
      sleep 2
    show_blocking_message_dialog "hit ok after smplayer is installed:"
    end
  end
end

#choose_dvd_drive_or_file(force_choose_only_dvd_drive) ⇒ Object

returns e:, volume_name, dvd_id or full_path.mkv, filename, ”



625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
# File 'lib/gui/base.rb', line 625

def choose_dvd_drive_or_file force_choose_only_dvd_drive
  opticals = DriveInfo.get_dvd_drives_as_openstruct
  if @saved_opticals == opticals && @_choose_dvd_drive_or_file
    # memoize...if disks haven't changed :)
    return @_choose_dvd_drive_or_file
  else
    @saved_opticals = opticals # save currently mounted disk list, so we know if we should re-select later... 
    # is this ok for os x?
  end

  has_at_least_one_dvd_inserted = opticals.find{|d| d.VolumeName }
  if !has_at_least_one_dvd_inserted && force_choose_only_dvd_drive
    show_blocking_message_dialog 'insert a dvd first' 
    raise 'no dvd found'
  end
  names = opticals.map{|d| d.Name + "\\" + " (" +  (d.VolumeName || 'Insert DVD to use') + ")"}
  if !force_choose_only_dvd_drive && !has_at_least_one_dvd_inserted
    names += ['No DVD mounted so click to choose a Local File (or insert DVD, then re-try)']
    used_local_file_option = true
  end
  
  count = 0
  opticals.each{|d| count += 1 if d.VolumeName}
  if count == 1 && !used_local_file_option
   # just choose it if there's only one disk available..
   p 'selecting only disk currently present in the various DVD drives [if you have more than one, that is]'
   selected_idx = opticals.index{|d| d.VolumeName}
   unless selected_idx
     show_blocking_message_dialog "Please insert a disk first"
     raise 'inset disk'
   end
  else
    dialog = get_disk_chooser_window names
    selected_idx = dialog.go_selected_index
  end
    if used_local_file_option
      raise unless selected_idx == 0 # it was our only option...they must have selected it!
      filename = new_existing_file_selector_and_select_file("Select yer previously grabbed from DVD file")
      assert_ownership_dialog
      return [filename, File.basename(filename), NonDvd]
    else
      disk = opticals[selected_idx]
      out = show_non_blocking_message_dialog "calculating current disk's unique id...if this pauses more than 10s then clean your DVD..."
      begin
      dvd_id = DriveInfo.md5sum_disk(disk.MountPoint)
      rescue Exception => e
      show_blocking_message_dialog e.to_s # todo a bit ugly...
     raise
    ensure
    out.dispose
    end
      @_choose_dvd_drive_or_file = [disk.DevicePoint, opticals[selected_idx].VolumeName, dvd_id]
      return @_choose_dvd_drive_or_file
    end
end

#choose_dvd_or_file_and_edl_for_it(force_choose_edl_file_if_no_easy_match = true) ⇒ Object



445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'lib/gui/base.rb', line 445

def choose_dvd_or_file_and_edl_for_it force_choose_edl_file_if_no_easy_match = true
  drive_or_file, dvd_volume_name, dvd_id = choose_dvd_drive_or_file false
  edl_path = EdlFilesChosen[dvd_id]
  if !edl_path
    edl_path = EdlParser.single_edit_list_matches_dvd(dvd_id)
    if !edl_path && force_choose_edl_file_if_no_easy_match
    message = "Please pick a DVD Edit List File (none or more than one were found that seem to match #{dvd_volume_name})--may need to create one, if one doesn't exist yet"
    show_blocking_message_dialog message
      edl_path = new_existing_file_selector_and_select_file(message, EdlParser::EDL_DIR)
    end
  end
  p 're/loading ' + edl_path # in case it has changed on disk
  if edl_path # sometimes they don't have to choose one [?]
    descriptors = nil
    begin
      descriptors = parse_edl edl_path
    rescue SyntaxError => e
      show_non_blocking_message_dialog("this file has an error--please fix then hit ok: \n" + edl_path + "\n " + e)
      raise e
    end
  end
  EdlFilesChosen[dvd_id] ||= edl_path
  [drive_or_file, dvd_volume_name, dvd_id, edl_path, descriptors]
end

#choose_file_and_edl_and_create_sxs_or_play(just_create_xbmc_dot_edl_file_instead_of_play) ⇒ Object

side by side stuff we haven’t really factored out yet, also doubles for both normal/create LODO



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/gui/normal.rb', line 121

def choose_file_and_edl_and_create_sxs_or_play just_create_xbmc_dot_edl_file_instead_of_play
  filename_mpg = new_existing_file_selector_and_select_file( "Pick moviefile (like moviename.mpg or video_ts/anything.ext)")
  edl_filename = new_existing_file_selector_and_select_file( "Pick an EDL file to use with it", EdlParser::EDL_DIR)
  assert_ownership_dialog
  if just_create_xbmc_dot_edl_file_instead_of_play
    descriptors = EdlParser.parse_file edl_filename
    # XBMC can use english timestamps
    edl_contents = MplayerEdl.convert_to_edl descriptors, add_secs_end = 0.0, begin_buffer_preference, splits = [], extra_time_to_all = 0.0, use_english_timestamps=true
    output_file = filename_mpg.gsub(/\.[^\.]+$/, '') + '.edl' # sanitize...
    File.write(output_file, edl_contents)
    raise unless File.exist?(output_file) # sanity
    show_blocking_message_dialog("created #{output_file}")
  else
    play_smplayer_edl_non_blocking [filename_mpg, edl_filename]
  end
end

#create_brand_new_dvd_edlObject



463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
# File 'lib/gui/create.rb', line 463

def create_brand_new_dvd_edl
 hashes, title_lengths = get_disk_info # has a prompt
 volume = hashes['volume_name']
 default_english_name = volume.split('_').map{|word| word.downcase.capitalize}.join(' ') # A Court A Jester
  english_name = get_user_input("Enter a human readable DVD description for #{volume}", default_english_name)

  # EDL versions:
 # nothing with disk_unique_id: probably dvd_start_offset 29.97
  # nothing without disk_unque_id: probably start_zero 29.97
  # 1.1: has timestamps_relative_to, I guess

  input = <<-EOL
# edl_version_version 1.1, sensible cinema v#{VERSION}
# comments can go be created by placing text after a # on any line, for example this one.
"name" => "#{english_name}",

"mutes" => [
  # an example line, uncomment the leading "#" to make it active
  # "0:00:01.0", "0:00:02.0", "profanity", "da..", 
],

"blank_outs" => [
  # an example line, uncomment the leading "#" to make it active
  # "00:03:00.0" , "00:04:00.0", "violence", "of some sort",
],

"source" => "dvd",
"volume_name" => "#{volume}",
"timestamps_relative_to" => ["dvd_start_offset","29.97"],
"disk_unique_id" => "#{hashes['disk_unique_id']}",
"dvd_title_track" => "#{hashes['dvd_title_track']}", # our guess for it
"dvd_title_track_length" => "#{hashes['dvd_title_track_length']}", 
# "not edited out stuff" => "some...",
# "closing thoughts" => "only ...",
# "subtitles_to_display_relative_path" => "some_file.srt" # if you want to display some custom subtitles alongside your movie
"dvd_title_track_start_offset" => "#{hashes['dvd_start_offset']}",
"dvd_nav_packet_offset" => #{hashes['dvd_nav_packet_offset'].inspect},
    EOL
  filename = EdlParser::EDL_DIR + "/edls_being_edited/" + english_name.gsub(' ', '_') + '.txt'
  filename.downcase!
  if File.exist?(filename)
   show_blocking_message_dialog 'don\'t want to overwrite a file in the edit dir that already has same name, opening it instead...'
 else
   File.write(filename, input)
  end
  open_file_to_edit_it filename
end

#create_new_for_file_or_netflixObject



528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
# File 'lib/gui/create.rb', line 528

def create_new_for_file_or_netflix
  names = ['movie file', 'netflix instant']
     dialog = DropDownSelector.new(self, names, "Select type")
     type = dialog.go_selected_value
     extra_options = {}
     if type == 'movie file'
       path = SwingHelpers.new_previously_existing_file_selector_and_go "Select file to create EDL for"
       guess_name = File.basename(path).split('.')[0..-2].join('.') # like yo.something.720p.HDTV.X264-DIMENSION.m4v maybe?
       extra_options['filename'] = File.basename path
       require 'lib/movie_hasher'
       extra_options['movie_hash'] = MovieHasher.compute_hash path
     else
       url = get_user_input "Please input the movies url (like http://www.netflix.com/Movie/Curious-George/70042686 )" #?
       if url =~ /netflix/
         guess_name = url.split('/')[-2]
       else
         show_blocking_message_dialog "non hulu/netflix? please report!"
         type = 'unknown'
         guess_name = url.split('/')[-1]
       end
       extra_options['url'] = url
     end
     english_name = get_user_input "Enter name of movie", guess_name.gsub(/[-._]/, ' ')
     filename = new_nonexisting_filechooser_and_go 'Pick new EDL filename', EdlParser::EDL_DIR + '/..', english_name.gsub(' ', '_') + '.txt'
     display_and_raise "needs .txt extension" unless filename =~ /\.txt$/i
     
     output = <<-EOL
# edl_version_version 1.1, created by sensible cinema v#{VERSION}
# comments can go be created by placing text after a # on any line, for example this one.
"name" => "#{english_name}",

"source" => "#{type}",
#{extra_options.map{|k, v| %!\n"#{k}" => "#{v}",\n!}}
"mutes" => [
  # an example line, uncomment the leading "#" to make it active
  # "0:00:01.0", "0:00:02.0", "profanity", "da..", 
],

"blank_outs" => [
  # an example line, uncomment the leading "#" to make it active
  # "00:03:00.0" , "00:04:00.0", "violence", "of some sort",
],

"timestamps_relative_to" => ["#{type}"],
# "not edited out stuff" => "some...",
# "closing thoughts" => "only ...",
# "subtitles_to_display_relative_path" => "some_file.srt" # if you want to display some custom subtitles alongside your movie
     EOL
     File.write filename, output
     open_file_to_edit_it filename

end

#display_and_raise(error_message) ⇒ Object



682
683
684
685
# File 'lib/gui/base.rb', line 682

def display_and_raise error_message
  show_blocking_message_dialog error_message
  raise error_message
end

#display_current_upconvert_setting_and_close_windowObject



230
231
232
233
234
# File 'lib/gui/upconvert.rb', line 230

def display_current_upconvert_setting_and_close_window
  change_upconvert_line_to_current
  show_blocking_message_dialog get_current_upconvert_as_phrase
  self.dispose
end

#do_create_edited_copy_via_file(should_prompt_for_start_and_end_times, exit_early_if_fulli_exists = false, watch_unedited = false) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/gui/create-file.rb', line 50

def do_create_edited_copy_via_file should_prompt_for_start_and_end_times, exit_early_if_fulli_exists = false, watch_unedited = false
  drive_or_file, dvd_volume_name, dvd_id, edit_list_path, descriptors = choose_dvd_or_file_and_edl_for_it
  
  descriptors = parse_edl(edit_list_path)
  if watch_unedited
    # reset them
    descriptors['mutes'] = descriptors['blank_outs'] = []
  end
  
  # LODO allow for spaces in the save_to filename
  if should_prompt_for_start_and_end_times
    start_time, end_time = get_start_stop_times_strings
  end
  dvd_friendly_name = descriptors['name']
  unless dvd_friendly_name
    drive_or_file, dvd_volume_name, dvd_id, edit_list_path, descriptors = choose_dvd_or_file_and_edl_for_it
    descriptors = parse_edl(edit_list_path)
    raise 'no dvd name in EDL?' + edit_list_path + File.read(edit_list_path)
  end
  
  dvd_title_track = get_title_track_string(descriptors)
  if dvd_id == NonDvd
    file_from = drive_or_file
  else
    file_from = get_ripped_filename_once dvd_friendly_name, dvd_title_track # we don't even care about the drive letter anymore...
  end
  
  sanity_check_file file_from
  
  save_to_edited = get_save_to_filename_from_user dvd_friendly_name
  fulli = MencoderWrapper.calculate_fulli_filename save_to_edited
  if exit_early_if_fulli_exists
    if fulli_dot_done_file_exists? save_to_edited
      return [true, fulli]
    end
    # make it create a dummy response file for us :)
    start_time = "00:00"
    end_time = "00:01"
  end
  
  if !fulli_dot_done_file_exists? save_to_edited
    show_non_blocking_message_dialog "Warning, the first pass through when editing file-wise, Sensible Cinema\nfirst needs to create a large temporary file that it can divide up easily.\nThis takes awhile, so you may need to get comfortable."
  end

  require_deletion_entry = true unless watch_unedited
  should_run_mplayer_after = should_prompt_for_start_and_end_times || exit_early_if_fulli_exists
  generate_and_run_bat_file save_to_edited, edit_list_path, descriptors, file_from, dvd_friendly_name, start_time, end_time, dvd_title_track, should_run_mplayer_after, require_deletion_entry
  [false, fulli] # false means it's running in a background thread :P
end

#download_7zipObject



49
50
51
52
53
54
55
56
57
58
# File 'lib/gui/dependencies.rb', line 49

def download_7zip
  Dir.mkdir('./vendor/cache') unless File.directory? 'vendor/cache' # development may not have it created yet... [?]
  unless File.exist? 'vendor/cache/7za.exe'
    Dir.chdir('vendor/cache') do
      print 'downloading unzipper (7zip--400K) ...'
      MainWindow.download("http://downloads.sourceforge.net/project/sevenzip/7-Zip/9.20/7za920.zip", "7za920.zip")
      system_blocking("../unzip.exe -o 7za920.zip") # -o means "overwrite" without prompting
    end
  end
end

#download_zip_file_and_extract(english_name, url, to_this) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/gui/dependencies.rb', line 60

def download_zip_file_and_extract english_name, url, to_this
  download_7zip
  Dir.chdir('vendor/cache') do
    file_name = url.split('/')[-1]
    print "downloading #{english_name} ..."
    MainWindow.download(url, file_name)
    system_blocking("7za e #{file_name} -y -o#{to_this}")
    puts 'done ' + english_name
    # creates vendor/cache/mencoder/mencoder.exe...
  end
end

#force_accept_file_style_licenseObject



17
18
19
20
21
22
23
# File 'lib/gui/dependencies.rb', line 17

def force_accept_file_style_license
   if !(LocalStorage['accepted_legal_copys'] == VERSION)
    require_blocking_license_accept_dialog 'Sensible Cinema', 'is_it_legal_to_copy_dvds.txt file', File.expand_path(File.dirname(__FILE__) + "/../../documentation/is_it_legal_to_copy_dvds.txt"), 
        'is_it_legal_to_copy_dvds.txt file', 'I acknowledge that I have read, understand, accept and agree to abide by the implications noted in the documentation/is_it_legal_to_copy_dvds.txt file.'
    LocalStorage['accepted_legal_copys'] = VERSION
  end
end

#force_accept_license_firstObject



9
10
11
12
13
14
15
# File 'lib/gui/dependencies.rb', line 9

def force_accept_license_first
  if !(LocalStorage['main_license_accepted'] == VERSION)
    require_blocking_license_accept_dialog 'Sensible Cinema', 'gplv3', 'http://www.gnu.org/licenses/gpl.html', 'Sensible Cinema license agreement', 
        "Sensible Cinema is distributed under the gplv3 (http://www.gnu.org/licenses/gpl.html).\nBY CLICKING \"accept\" YOU SIGNIFY THAT YOU HAVE READ, UNDERSTOOD AND AGREED TO ABIDE BY THE TERMS OF THIS AGREEMENT"
    LocalStorage['main_license_accepted'] = VERSION
  end
end

#fulli_dot_done_file_exists?(save_to_edited) ⇒ Boolean

Returns:

  • (Boolean)


151
152
153
154
# File 'lib/gui/create-file.rb', line 151

def fulli_dot_done_file_exists? save_to_edited
  fulli = MencoderWrapper.calculate_fulli_filename save_to_edited
  File.exist?(fulli + ".done")
end

#generate_and_run_bat_file(save_to, edit_list_path, descriptors, file_from, dvd_title, start_time, end_time, dvd_title_track, run_mplayer, require_deletion_entry) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/gui/create-file.rb', line 162

def generate_and_run_bat_file save_to, edit_list_path, descriptors, file_from, dvd_title, start_time, end_time, dvd_title_track, run_mplayer, require_deletion_entry
  LocalStorage['last_params'] = [save_to, edit_list_path, descriptors, file_from, dvd_title, start_time, end_time, dvd_title_track, run_mplayer, require_deletion_entry]
  begin
    commands = get_mencoder_commands descriptors, file_from, save_to, start_time, end_time, dvd_title_track, require_deletion_entry
  rescue MencoderWrapper::TimingError => e
    show_blocking_message_dialog("Appears you chose a time frame with no deletion segment in it--please try again:" + e)
    return
  rescue Errno::EACCES => e
    show_blocking_message_dialog("Appears a file on the system is locked: perhaps you need to close down some instance of mplayer?" + e)
    return
  end
  temp_dir = Dir.tmpdir
  temp_file = temp_dir + '/vlc.temp.bat'
  File.write(temp_file, commands)
  popup_message = <<-EOL
    Applying EDL #{File.basename edit_list_path} 
       to movie file #{file_from} (#{dvd_title}).
    Saving to #{save_to}.
  EOL
  if !fulli_dot_done_file_exists?(save_to)
    popup_message += "This will take quite awhile (several hours, depending on movie size), \nsince it needs to first create an intermediate file for more accurate splitting.\nit will prompt you with a chime noise when it is done.\n
    You can close this window and minimize sensible cinema \nto continue using your computer while it runs in the background.\nYou can see progress via the progress bar.\n"
  end
  
  if !start_time
    # assume a full run..
    popup_message += <<-EOL
      NB that the created file will be playable only with VLC (possibly also with smplayer), 
      but probably not with windows media player.
    EOL
  end
  
  popup = show_non_blocking_message_dialog(popup_message, "OK")

  # allow our popups to still be serviced while it is running
  @background_thread = Thread.new { run_batch_file_commands_and_use_output_somehow commands, save_to, file_from, run_mplayer }
  when_thread_done(@background_thread) { popup.dispose }
  # LODO warn if they will overwrite a file in the end...
end

#get_current_max_width_resolutionObject



246
247
248
249
# File 'lib/gui/upconvert.rb', line 246

def get_current_max_width_resolution
  # choose width of widest monitor (why would they display it on the other, right?)
  java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment.getScreenDevices.map{|gd| gd.display_mode.width}.max.to_i
end

#get_current_upconvert_as_phraseObject



236
237
238
239
240
241
242
243
244
# File 'lib/gui/upconvert.rb', line 236

def get_current_upconvert_as_phrase
  settings = LocalStorage[UpConvertEnglish]
  out = "Upconvert options are now #{  settings ? "set to #{settings} style" : "NOT SET"}"
  if settings
    multiple = LocalStorage[ScreenMultipleFactor]
    out += " (screen multiplier #{multiple}*#{get_current_max_width_resolution} = #{(multiple * get_current_max_width_resolution).to_i}px)."
  end
  out
end

#get_disk_chooser_window(names) ⇒ Object



722
723
724
# File 'lib/gui/base.rb', line 722

def get_disk_chooser_window names
  DropDownSelector.new(self, names, "Click to select DVD drive")
end

#get_disk_infoObject



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/gui/create.rb', line 334

def get_disk_info
 drive, volume_name, dvd_id = choose_dvd_drive_or_file true # require a real DVD disk :)
  # display it, allow them to copy and paste it out
 out_hashes = {}
 out_hashes['disk_unique_id'] = dvd_id
 out_hashes['volume_name'] = volume_name
  popup = show_non_blocking_message_dialog "calculating DVD title sizes..."
  command = "mplayer -vo direct3d dvdnav:// -nocache -dvd-device #{drive} -identify -frames 0 2>&1"
  puts command
  title_lengths_output = `#{command}`
  popup.close
  edit_list_path = EdlParser.single_edit_list_matches_dvd(dvd_id)
  if edit_list_path
	  parsed = parse_edl edit_list_path
    title_to_get_offset_of = get_title_track_string(parsed)
  else
    title_to_get_offset_of = nil
  end
  title_lengths = title_lengths_output.split("\n").select{|line| line =~ /TITLE.*LENGTH/}
  # ID_DVD_TITLE_4_LENGTH=365.000
  titles_with_length = title_lengths.map{|name| name =~ /ID_DVD_TITLE_(\d+)_LENGTH=([\d\.]+)/; [$1, $2.to_f]}
	  if titles_with_length.length > 50
 show_blocking_message_dialog "this DVD has > 50 titles, this may mean that our 'guess' for the main title will be off, please double check the right number\nby starting the main movie in VLC then Playback menu -> title to see which number it is on."
	  end
  largest_title = titles_with_length.max_by{|title, length| length}
 if !largest_title
   display_and_raise "unable to parse title lengths? maybe need to clean disk first? #{title_lengths_output}"
	  end
 largest_title = largest_title[0]
  title_to_get_offset_of ||= largest_title
  out_hashes['dvd_title_track'] = title_to_get_offset_of
 out_hashes['dvd_title_track_length'] = titles_with_length.detect{|title, length| title == title_to_get_offset_of}[1]
  offsets = calculate_dvd_start_offset(title_to_get_offset_of, drive)
	start_offset = offsets[:mpeg_start_offset]
 out_hashes['dvd_start_offset'] = start_offset
  out_hashes['dvd_nav_packet_offset'] = offsets[:dvd_nav_packet_offset]
 [out_hashes, title_lengths]
end

#get_drive_with_most_space_with_slashObject



615
616
617
# File 'lib/gui/base.rb', line 615

def get_drive_with_most_space_with_slash
  DriveInfo.get_drive_with_most_space_with_slash
end

#get_dvd_playback_options(descriptors) ⇒ Object



414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
# File 'lib/gui/base.rb', line 414

def get_dvd_playback_options descriptors
  out = []
  
  nav, mpeg_time = descriptors['dvd_nav_packet_offset'] # like [0.5, 0.734067]
  if nav
 mpeg_time *= 1/1.001 # -> 29.97 fps
    offset_time = mpeg_time - nav
  else
  # readings: 0.213  0.173 0.233 0.21 0.18 0.197 they're almost all right around 0.20...
    show_blocking_message_dialog "error--your DVD EDL doesn\'t list a start offset time [dvd_nav_packet_offset] which is needed for precise accurate timing. Please run\nadvanced mode -> Display information about current DVD\nand add it to the EDL. Using a default for now...if you tweak any timing info you may want to set this more accurately first!"
    offset_time = 0.20
  end
	  raise if offset_time <= 0 # unexpected...
	  # -osd-add is because the initial NAV packet is "x" seconds off from the mpeg, and since 
	  # we have it set within mplayer to "prefer to just give you the MPEG time when you haven't passed a DVD block"
	  # we wanted to match that more precisely once we did get past it.
	  # so basically today we are trying to "match" the underlying MPEG time well. Which is wrong, of course.
	  # either match the file or match the DVD, punk!
	  out << "-osd-add #{ "%0.3f" % offset_time}"
  out.join(' ')
end

#get_freespace(path) ⇒ Object



611
612
613
# File 'lib/gui/base.rb', line 611

def get_freespace path
  JFile.new(File.dirname(path)).get_usable_space
end

#get_mencoder_commands(descriptors, file_from, save_to, start_time, end_time, dvd_title_track, require_deletion_entry) ⇒ Object

to make it stubbable :)



157
158
159
160
# File 'lib/gui/create-file.rb', line 157

def get_mencoder_commands descriptors, file_from, save_to, start_time, end_time, dvd_title_track, require_deletion_entry
  delete_partials = true unless start_time # in case anybody wants to look really really close for now
  MencoderWrapper.get_bat_commands descriptors, file_from, save_to, start_time, end_time, dvd_title_track, delete_partials, require_deletion_entry
end

#get_ripped_filename_once(dvd_title, dvd_title_track) ⇒ Object



120
121
122
123
124
125
# File 'lib/gui/create-file.rb', line 120

def get_ripped_filename_once dvd_title, dvd_title_track
  @_get_ripped_filename_once ||=
  begin
    new_existing_file_selector_and_select_file "Please choose the file that is your ripped equivalent of #{dvd_title} (title track #{dvd_title_track}) (.mpg or .ts--see file documentation/how_to_get_files_from_dvd.txt)"
  end
end

#get_same_drive_friendly_clean_temp_dir(suffix) ⇒ Object



219
220
221
222
223
224
225
226
227
228
# File 'lib/gui/upconvert.rb', line 219

def get_same_drive_friendly_clean_temp_dir suffix
    output_dir = Dir.tmpdir
    if File.get_root_dir(output_dir) != File.get_root_dir(Dir.pwd) # you are hosed!
      output_dir = File.get_root_dir(Dir.pwd) # we'll raise if it's not writable...
    end
    output_dir = output_dir + '/' + suffix
    FileUtils.rm_rf output_dir
    Dir.mkdir output_dir
    output_dir
end

#get_save_to_filename_from_user(dvd_title) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/gui/create-file.rb', line 127

def get_save_to_filename_from_user dvd_title
  @_get_save_to_filename_from_user ||=
  begin
    save_to_file_name = dvd_title + ' edited version'
    save_to_file_name = save_to_file_name.gsub(' ', '_').gsub( /\W/, '') + ".avi" # no punctuation or spaces for now, to not complicate...
    save_to = new_nonexisting_filechooser_and_go "Pick where to save #{dvd_title} edited version to", nil, get_drive_with_most_space_with_slash + save_to_file_name
    raise 'no spaces allowed yet' if save_to =~ / /
    begin
      a = File.open(File.dirname(save_to) + "/test_file_to_see_if_we_have_permission_to_write_to_this_folder", "w")
      a.close
      File.delete a.path
    rescue Errno::EACCES => e
      show_blocking_message_dialog "unable to write to that directory, please pick again: " + e.to_s
      raise 'pick again!'
    end
    freespace = get_freespace(save_to)
    if freespace < 8_000_000_000
      show_blocking_message_dialog("Warning: there may not be enough space on the disk for #{save_to} 
      (depending on DVD size, you may need around 10G free--you have #{freespace/1_000_000_000}GB free).  Click OK to continue.")
    end
    save_to.gsub(/\.avi$/, '')
  end
end

#get_set_preference(name, english_name) ⇒ Object



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/gui/dependencies.rb', line 195

def get_set_preference name, english_name
  old_preference = LocalStorage[name]
  old_class = old_preference.class
	  
	  new_preference = get_user_input("Enter value for #{english_name}", old_preference)
  display_and_raise 'enter something like 0.0' if new_preference.empty?
  if old_class == Float
    new_preference = new_preference.to_f
  elsif old_class == String
    # leave same
  else
    raise 'unknown type?' + old_class.to_s
  end
  LocalStorage[name] = new_preference
end

#get_srt_filename(descriptors, edl_filename) ⇒ Object



164
165
166
167
168
169
170
171
# File 'lib/gui/base.rb', line 164

def get_srt_filename descriptors, edl_filename
  path = descriptors['subtitles_to_display_relative_path'] if descriptors
  if path
    path = File.expand_path(File.dirname(edl_filename) + '/' + path)
    raise 'nonexisting srt file must be relative to the edl file...' + path unless File.exist? path
  end
  path
end

#get_start_stop_times_stringsObject



435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
# File 'lib/gui/create.rb', line 435

def get_start_stop_times_strings
    # only show this message once :)
    @show_block ||= show_blocking_message_dialog(<<-EOL, "Preview")
      Ok, let's preview just a portion of it. 
      Note that you'll want to preview a section that wholly includes an edit section within it.
      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.
      Also note that the first time you preview a section of a video, it will take a long time (like an hour) as it sets up the entire video for processing.
      Subsequent previews will be faster, though, as long as you use the same filename, as it won't have to re-set it up for processing.
      Also note that if you change your edit list, you'll need to close, and restart the video to be able to see it with your new settings.
    EOL
    old_start = LocalStorage['start_time']
    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)", LocalStorage['start_time'])
    default_end = LocalStorage['end_time']
    if start_time and start_time != old_start
      default_end = EdlParser.translate_string_to_seconds(start_time) + 10
      default_end = EdlParser.translate_time_to_human_readable(default_end)
    end
    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)", default_end)
    unless start_time and end_time
      # this one is raw showMessageDialog...
      JOptionPane.showMessageDialog(nil, " Please choose start and end", "Failed", JOptionPane::ERROR_MESSAGE)
      return
    end
    LocalStorage['start_time'] = start_time
    LocalStorage['end_time'] = end_time
    [start_time, end_time]
end

#get_temp_file_name(name_with_ext) ⇒ Object



726
727
728
# File 'lib/gui/base.rb', line 726

def get_temp_file_name name_with_ext
  File.dirname(EdlTempFile) + '/' + name_with_ext
end

#get_title_track_string(descriptors, use_default_of_one = true) ⇒ Object



158
159
160
161
162
# File 'lib/gui/base.rb', line 158

def get_title_track_string descriptors, use_default_of_one = true
  given = descriptors["dvd_title_track"] 
  given ||= "1" if use_default_of_one
  given
end

#get_upconvert_secondary_settingsObject



266
267
268
# File 'lib/gui/upconvert.rb', line 266

def get_upconvert_secondary_settings
  LocalStorage[UpConvertKeyExtra]
end

#get_upconvert_vf_settingsObject



251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/gui/upconvert.rb', line 251

def get_upconvert_vf_settings
  template = LocalStorage[UpConvertKey]
  if template
    screen_multiple = LocalStorage[ScreenMultipleFactor]
    upc = template.gsub('SCREEN_X', (get_current_max_width_resolution*screen_multiple).to_i.to_s) # has to be an integer...
    upc = 'pullup,softskip,' + upc
    show_non_blocking_message_dialog 'using upconvert settings ' + upc
    p 'using upconvert settings: ' + upc
    upc
  else
    p 'not using any specific upconversion-ing'
    # pullup, softskip -- might slow things down too much for slow cpus
  end
end

#get_user_input(message, default = '', cancel_ok = false) ⇒ Object



589
590
591
# File 'lib/gui/base.rb', line 589

def get_user_input(message, default = '', cancel_ok = false)
  SwingHelpers.get_user_input message, default, cancel_ok
end

#hard_exitObject



26
# File 'lib/gui/normal.rb', line 26

def hard_exit; java::lang::System.exit 0; end

#increment_button_location(how_much = 30) ⇒ Object



204
205
206
207
# File 'lib/gui/base.rb', line 204

def increment_button_location how_much = 30
  @starting_button_y += how_much
  setSize @button_width+80, @starting_button_y + 50
end

#is_dvd?(drive_or_file) ⇒ Boolean

Returns:

  • (Boolean)


472
473
474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/gui/base.rb', line 472

def is_dvd? drive_or_file
  # it's like a/b/VIDEO_TS or d:/
  if File.basename(File.dirname(drive_or_file)) == 'VIDEO_TS' 
    # /a/b/c/VIDEO_TS/yo.vob
    true
  elsif File.exist?(drive_or_file + '/VIDEO_TS')
    # d:\
    true
  elsif OS.mac? && (drive_or_file =~ /\/dev\/rdisk\d+/)
    true
  else
   false
  end
end

#new_child_windowObject

a window that when closed doesn’t bring the whole app down



217
218
219
220
221
222
223
224
225
# File 'lib/gui/base.rb', line 217

def new_child_window
  child = MainWindow.new true, []
  child.setDefaultCloseOperation(JFrame::DISPOSE_ON_CLOSE) # don't exit on close
  child.parent=self # this should have failed in the PPL
  # make both windows visible by moving the child down and to the right of its parent
  x, y = self.get_location.x, self.get_location.y
  child.set_location(x + 100, y + 100)
  child
end

#new_existing_file_selector_and_select_file(title, dir = nil) ⇒ Object

also caches directory previously selected …



563
564
565
566
567
568
569
570
571
572
573
574
# File 'lib/gui/base.rb', line 563

def new_existing_file_selector_and_select_file title, dir = nil
  bring_to_front unless OS.mac? # causes duplicate prompts or something?
  unique_trace = caller.inspect
  if LocalStorage[unique_trace]
    dir = LocalStorage[unique_trace]
  end
  p 'using system default dir' unless dir # happens more frequently after code changes alter the path :P
  p 'using lookup dir ' + dir, LocalStorage[unique_trace] if $VERBOSE
  got = SwingHelpers.new_previously_existing_file_selector_and_go title, dir
  LocalStorage[unique_trace] = File.dirname(got)
  got
end

#new_jbutton(title, tooltip = nil) ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/gui/base.rb', line 181

def new_jbutton title, tooltip = nil
  button = JButton.new title
  button.tool_tip = tooltip
  button.set_bounds(44, @starting_button_y, @button_width, 23)
  @panel.add button
  @buttons << button
  if block_given? # allow for new_jbutton("xx") do ... end [this is possible through some miraculous means LOL]
    button.on_clicked { yield }
  end
  increment_button_location
  button
end

#new_nonexisting_filechooser_and_go(title = nil, default_dir = nil, default_file = nil) ⇒ Object



557
558
559
560
# File 'lib/gui/base.rb', line 557

def new_nonexisting_filechooser_and_go title = nil, default_dir = nil, default_file = nil
  bring_to_front unless OS.mac? # causes triples on mac! TODO rdp
  JFileChooser.new_nonexisting_filechooser_and_go title, default_dir, default_file
end

#normalize_path(path) ⇒ Object

converts to full path, 8.3 if on doze



731
732
733
734
# File 'lib/gui/base.rb', line 731

def normalize_path path
  path = File.expand_path path
  path = EightThree.convert_path_to_8_3 path if OS.doze?
end

#open_edl_file_when_done(thred, filename) ⇒ Object



5
6
7
8
9
10
# File 'lib/gui/create.rb', line 5

def open_edl_file_when_done thred, filename
  Thread.new {
    thred.join
    open_file_to_edit_it filename
  }
end

#open_file_to_edit_it(filename, options = {}) ⇒ Object

:start_minimized is the only option



544
545
546
547
548
549
550
551
552
553
554
555
# File 'lib/gui/base.rb', line 544

def open_file_to_edit_it filename, options = {} # :start_minimized is the only option
  if OS.windows?
    if options[:start_minimized]
      system_non_blocking "start /min notepad \"#{filename}\""
    else
      system_non_blocking "notepad \"#{filename}\""
    end
  else
    # ignore minimized :P
    system_non_blocking "open -a TextEdit \"#{filename}\""
  end
end

#parse_edl(path) ⇒ Object



607
608
609
# File 'lib/gui/base.rb', line 607

def parse_edl path
  EdlParser.parse_file path
end

#play_dvd_smplayer_unedited(use_mplayer_instead) ⇒ Object



403
404
405
406
407
408
409
410
411
412
# File 'lib/gui/base.rb', line 403

def play_dvd_smplayer_unedited use_mplayer_instead
  drive_or_file, dvd_volume_name, dvd_id, edl_path_maybe_nil, descriptors = choose_dvd_or_file_and_edl_for_it(force_choose_edl_file_if_no_easy_match = true)
  title_track_maybe_nil = get_title_track_string(descriptors, false)
  if is_dvd?(drive_or_file)
    dvd_options = get_dvd_playback_options(descriptors)
  else
    dvd_options = ''
  end
  run_smplayer_non_blocking drive_or_file, title_track_maybe_nil, dvd_options, use_mplayer_instead, true, false, get_srt_filename(descriptors, edl_path_maybe_nil)
end

#play_smplayer_edl_non_blocking(optional_file_with_edl_path = nil, extra_mplayer_commands_array = [], force_mplayer = false, start_full_screen = true, add_secs_end = 0, add_secs_begin = begin_buffer_preference, show_subs = false) ⇒ Object



493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
# File 'lib/gui/base.rb', line 493

def play_smplayer_edl_non_blocking optional_file_with_edl_path = nil, extra_mplayer_commands_array = [], force_mplayer = false, start_full_screen = true, add_secs_end = 0, 
 add_secs_begin = begin_buffer_preference, show_subs = false
  if we_are_in_create_mode
    assert(add_secs_begin == 0 && add_secs_end == 0)
  end
  if optional_file_with_edl_path
    drive_or_file, edl_path = optional_file_with_edl_path
    dvd_id = NonDvd # fake it out...LODO a bit smelly/ugly
  else
    drive_or_file, dvd_volume_name, dvd_id, edl_path, descriptors = choose_dvd_or_file_and_edl_for_it
  end
  start_add_this_to_all_ts = 0
	  
  if edl_path # some don't have one [?]
 begin
# TODO combine these 2 methods yipzers
      descriptors = EdlParser.parse_file edl_path
     splits = [] # TODO not pass as parameter either
      edl_contents = MplayerEdl.convert_to_edl descriptors, add_secs_end, add_secs_begin, splits, start_add_this_to_all_ts # add a sec to mutes to accomodate for mplayer's oddness..
      File.write(EdlTempFile, edl_contents)
      extra_mplayer_commands_array << "-edl #{EdlTempFile}" 
		rescue SyntaxError => e
show_blocking_message_dialog "unable to parse file! #{edl_path} #{e}"
raise
		end
    title_track = get_title_track_string(descriptors)
  end
  
  if is_dvd?(drive_or_file)
    # it's a DVD of some sort
    extra_mplayer_commands_array << get_dvd_playback_options(descriptors)
  else
   # it's a file
    # check if it has a start offset...
    all =  `ffmpeg -i "#{drive_or_file}" 2>&1` # => Duration: 01:35:49.59, start: 600.000000
    all =~ /Duration.*start: ([\d\.]+)/
    start = $1.to_f
    if start > 1 # LODO dvd's themselves start at 0.3 [sintel], but I don't think much higher than that never seen it...
      show_non_blocking_message_dialog "Warning: file seems to start at an extra offset, adding it to the timestamps... #{start}
        maybe not compatible with XBMC, if that's what you use, and you probably don't" # LODO test it XBMC...
      start_add_this_to_all_ts = start
    end
  end
  
  run_smplayer_non_blocking drive_or_file, title_track, extra_mplayer_commands_array.join(' '), force_mplayer, show_subs, start_full_screen, get_srt_filename(descriptors, edl_path)
end


540
541
542
# File 'lib/gui/base.rb', line 540

def print *args
  Kernel.print *args # avoid bin\sensible-cinema.rb:83:in `system_blocking': cannot convert instance of class org.jruby.RubyString to class java.awt.Graphics (TypeError)
end

#repeat_last_copy_dvd_to_hard_driveObject



116
117
118
# File 'lib/gui/create-file.rb', line 116

def repeat_last_copy_dvd_to_hard_drive
  generate_and_run_bat_file(*LocalStorage['last_params'])
end

#require_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) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/gui/dependencies.rb', line 140

def require_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
  puts 'Please confirm license agreement in open window before proceeding.'
  
  message ||= "Sensible Cinema requires a separately installed program (#{program}), not yet installed.
    You can install this program manually to the vendor/cache subdirectory, or Sensible Cinema can download it for you.
    By clicking accept, below, you are confirming that you have read and agree to be bound by the
    terms of its license (the #{license_name}), located at #{license_url_should_also_be_embedded_by_you_in_message}.  
    Click 'View License' to view it.  If you do not agree to these terms, click 'Cancel'.  You also agree that this is a 
    separate program, with its own distribution, license, ownership and copyright.  
    You agree that you are responsible for the download and use of this program, within sensible cinema or otherwise."
  answer = JOptionPane.show_select_buttons_prompt message, :no => "I have read and Accept the terms of the #{license_name} License Agreement.", :yes => "View #{license_name}"
  assert_confirmed_dialog answer, license_url_should_also_be_embedded_by_you_in_message
  p 'confirmation of sensible cinema related license duly noted of: ' + license_name # LODO require all licenses together :P
end

#run_batch_file_commands_and_use_output_somehow(batch_commands, save_to, file_from, run_mplayer_after_done) ⇒ Object



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/gui/create-file.rb', line 202

def run_batch_file_commands_and_use_output_somehow batch_commands, save_to, file_from, run_mplayer_after_done
  @buttons.each{|b| b.set_enabled false}
  success = true
  lines = batch_commands.lines.to_a
  total_size = lines.length.to_f
  @progress_bar.visible=true
  @progress_bar.set_value(10) # start at 10% always, so they can see something.
  lines.each_with_index{|line, idx|
    if success
      puts "running #{line}"
      success = system_blocking(line, true)
      if !success
        puts "\n", 'line failed: ' + line + "\n" + '   see troubleshooting section in README.txt file! ignoring further processing commands...'
      end
    end
    @progress_bar.set_value(10 + idx/total_size*90)
  }
  @progress_bar.visible=false
  @buttons.each{|b| b.set_enabled true}
  if success
    saved_to = save_to + '.avi'
    if run_mplayer_after_done
      run_smplayer_non_blocking saved_to, nil, '', false, false, true, nil
    else
      size_original = File.size(file_from)
      size_edited_version = File.size(saved_to)
      if size_edited_version < (size_original*0.5)
        show_blocking_message_dialog("Warning: file sizes differs by more than 50%--it's possible that transcoding failed somehow. Orig: #{size_original} edited: #{size_edited_version}")
      end
      show_in_explorer saved_to
      PlayAudio.new(File.expand_path(File.dirname(__FILE__)) + "/../../vendor/music.wav").start # let it finish on its own :P
      msg =  "Done--you may now watch file\n #{saved_to}\n in VLC player (or possibly smplayer)"
      puts msg # for being able to tell it's done on the command line
      show_blocking_message_dialog msg
    end
  else
    SwingHelpers.show_blocking_message_dialog "Failed--please examine console output and report back!\nAlso consult the documentation/troubleshooting file.", "Failed", JOptionPane::ERROR_MESSAGE
  end
end

#run_smplayer_blocking(play_this, title_track_maybe_nil, passed_in_extra_options, force_use_mplayer, show_subs, start_full_screen, srt_filename) ⇒ Object

basically run mplayer/smplayer on a file or DVD



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/gui/base.rb', line 234

def run_smplayer_blocking play_this, title_track_maybe_nil, passed_in_extra_options, force_use_mplayer, show_subs, start_full_screen, srt_filename
  raise unless passed_in_extra_options # cannot be nil
  extra_options = []
  # -framedrop is for slow CPU's
  # same with -autosync to try and help it stay in sync... -mc 0.03 is to A/V correct 1s audio per 2s video
  # -hardframedrop might help but hurts the eyes just too much
  extra_options << "-framedrop" # even in create mode, if the audio ever gets off, we're hosed with making accurate timestamps...so drop, until I hear otherwise...
  extra_options << "-mc 2"
  extra_options << "-autosync 30" 

  if we_are_in_create_mode
    extra_options << "-osdlevel 2"
    extra_options << "-osd-verbose" if we_are_in_developer_mode?		
  end
  extra_options << "-osd-fractions 1"
  
  if !show_subs && !srt_filename
    # disable all subtitles :P
    extra_options << "-nosub -noautosub -forcedsubsonly -sid 1000"
  end
 if srt_filename
   extra_options << "-sub #{srt_filename}"
 else
    extra_options << "-alang en"
    extra_options << "-slang en"
 end

  force_use_mplayer ||= OS.mac?
  parent_parent = File.basename(File.dirname(play_this))
  if parent_parent == 'VIDEO_TS'
    # case d:\yo\VIDEO_TS\title0.vob
    dvd_device_dir = normalize_path(File.dirname(play_this))
    play_this = "\"dvdnav://#{title_track_maybe_nil}/#{dvd_device_dir}/..\""
  elsif File.exist?(play_this + '/VIDEO_TS') || (play_this =~ /\/dev\/rdisk\d/)
    # case d:\ where d:\VIDEO_TS exists [DVD mounted in drive, or DVD dir] or mac's /dev/rdisk1
    play_this = "\"dvdnav://#{title_track_maybe_nil}/#{play_this}\""
  else
    # case g:\video\filename.mpg
    # leave it the same...
  end
  if play_this =~ /dvdnav/ && title_track_maybe_nil
    extra_options << "-msglevel identify=4" # prevent smplayer from using *forever* to look up info on DVD's with -identify ...
  end
  
  extra_options << "-mouse-movements #{get_upconvert_secondary_settings}" # just in case smplayer also needs -mouse-movements... :) LODO
  extra_options << "-lavdopts threads=#{OS.cpu_count}" # just in case this helps [supposed to with h.264] # NB fast *crashes* doze...
  if force_use_mplayer
    extra_options << "-font #{File.expand_path('vendor/subfont.ttf')}"
 key_strokes = <<-EOL
RIGHT seek +10
LEFT seek -10
DOWN seek -60
UP seek +60
ENTER {dvdnav} dvdnav select	  
MOUSE_BTN0 {dvdnav} dvdnav select
MOUSE_BTN0_DBL vo_fullscreen
MOUSE_BTN2 vo_fullscreen
KP_ENTER dvdnav select
# some for os x, some for doze. huh?
   EOL
   conf_file = File.expand_path './mplayer_input_conf'
   File.write conf_file, key_strokes
   extra_options << "-volume 100" # why start low? mplayer why oh why LODO
   if OS.windows?
    # direct3d for windows 7 old nvidia cards' sake [yipes] and also dvdnav sake
    extra_options << "-vo direct3d"
    conf_file = conf_file[2..-1] # strip off drive letter, which it doesn't seem to like no sir
   end
   if start_full_screen
     extra_options << "-fs"
     upconv = get_upconvert_vf_settings
     upconv = "-vf #{upconv}" if upconv.present?
   else
    upconv = ""
   end
   if OS.doze?
     mplayer_loc = LocalModifiedMplayer
     assert File.exist?(mplayer_loc)
   else
     mplayer_loc = "mplayer"
   end
   c = "#{mplayer_loc} #{extra_options.join(' ')} #{upconv} -input conf=\"#{conf_file}\" #{passed_in_extra_options} \"#{play_this}\" "
  else
    if OS.windows?
      extra_options << "-vo direct3d" # more light nvidia...should be ok...this wastes cpu...but we have to have it I guess...
    end
    set_smplayer_opts extra_options.join(' ') + " " + passed_in_extra_options, get_upconvert_vf_settings, show_subs
    c = "smplayer \"#{play_this}\" -config-path \"#{File.dirname  EightThree.convert_path_to_8_3(SMPlayerIniFile)}\" " 
    c += " -fullscreen " if start_full_screen
    if !we_are_in_create_mode
      #c += " -close-at-end " # still too unstable...
    end
  end
  puts c
  system_blocking c
end

#run_smplayer_non_blocking(*args) ⇒ Object



227
228
229
230
231
# File 'lib/gui/base.rb', line 227

def run_smplayer_non_blocking *args
  @background_thread = Thread.new {
    run_smplayer_blocking *args
  }
end

#sanity_check_file(filename) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/gui/create-file.rb', line 100

def sanity_check_file filename
  out = `ffmpeg -i #{filename} 2>&1`
  print out
  unless out =~ /Duration.*start: 0.00/ || out =~ /Duration.*start: 600/
    show_blocking_message_dialog 'file\'s typically have the movie start at zero, this one doesn\'t? Please report.' + out
    raise # give up, as otherwise we're 0.3 off, I think...hmm...
  end
  if filename =~ /\.mkv/i
    show_blocking_message_dialog "warning .mkv files from makemkv have been known to be off timing wise, please convert to a .ts file using tsmuxer first if it did come from makemkv"
  else
    if filename !~ /\.(ts|mpg|mpeg)$/i
      show_blocking_message_dialog("warning: file #{filename} is not a .mpg or .ts file--conversion may not work properly all the way [produce a truncated file], but we can try it if you want...") 
    end
  end
end

#set_individual_preferencesObject



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/gui/dependencies.rb', line 179

def set_individual_preferences
     get_set_preference 'mplayer_beginning_buffer', "How much extra \"buffer\" time to add at the beginning of all cuts/mutes in normal mode [for added safety sake]."
     if JOptionPane.show_select_buttons_prompt("Would you like to use this with Zoom Player MAX's scene cuts [3rd party player program, costs $], or MPlayer et al [free]", :no => "ZoomPlayer MAX", :yes => "MPlayer/VLC/DVD-Navigator [all free]") == :no
       LocalStorage['have_zoom_button'] = true
     else
    LocalStorage['have_zoom_button'] = false
  end
  # TODO break these out into create mode prefs versus human [?]
     if JOptionPane.show_select_buttons_prompt("Would you like to enable obscure options, like using keyboard shortcuts to create EDL files on the fly, or creating euphemized .srt files (you probably don't)?") == :yes
       LocalStorage['prompt_obscure_options'] = true
     else
    LocalStorage['prompt_obscure_options'] = false
  end
  true
end

#set_smplayer_opts(to_this, video_settings, show_subs = false) ⇒ Object



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/gui/base.rb', line 334

def set_smplayer_opts to_this, video_settings, show_subs = false
  p 'setting smplayer extra opts to this:' + to_this
  old_prefs = File.read(SMPlayerIniFile) rescue ''
  unless old_prefs.length > 0
    # LODO double check the rest here...
    old_prefs = "[%General]\nmplayer_bin=\n[advanced]\nmplayer_additional_options=\nmplayer_additional_video_filters=\n[subtitles]\nautoload_sub=false\n[performance]\npriority=3" 
  end
  raise to_this if to_this =~ /"/ # unexpected, unfortunately... <smplayer bug>
  assert new_prefs = old_prefs.gsub(/mplayer_additional_options=.*/, "mplayer_additional_options=#{to_this}")
  assert new_prefs.gsub!(/autoload_sub=.*$/, "autoload_sub=#{show_subs.to_s}")
  raise 'unexpected' if get_upconvert_vf_settings =~ /"/
  assert new_prefs.gsub!(/mplayer_additional_video_filters=.*$/, "mplayer_additional_video_filters=\"#{video_settings}\"")
  raise 'smplayer on non doze not expected...' unless OS.doze?
  mplayer_to_use = LocalModifiedMplayer  
  assert File.exist?(mplayer_to_use)
  new_value = "\"" + mplayer_to_use.to_filename.gsub("\\", '/') + '"' # forward slashes. Weird.
  assert new_prefs.gsub!(/mplayer_bin=.*$/, "mplayer_bin=" + new_value)
  # now some less important ones...
  new_prefs.gsub!(/priority=.*$/, "priority=3") # normal priority...scary otherwise! lodo tell smplayer...
  # enable dvdnav navigation, just for kicks I guess.
  new_prefs.gsub!(/use_dvdnav=.*$/, "use_dvdnav=true")
  
  FileUtils.mkdir_p File.dirname(SMPlayerIniFile)
  File.write(SMPlayerIniFile, new_prefs)
  new_prefs.each_line{|l| print l if l =~ /additional_video/} # debug
end

#setup_create_buttonsObject



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/gui/create.rb', line 12

def setup_create_buttons
	  # only create mode needs this uh guess
  EdlParser.on_any_file_changed_single_cached_thread { DriveInfo.notify_all_drive_blocks_that_change_has_occured }
	  
 add_text_line 'Normal playback Options:'
  new_jbutton("Display Standard Playback Options") do
    window = new_child_window
    window.setup_normal_buttons
  end
  
  add_text_line 'Create: Edit Decision List File Options:'
  
  @open_current = new_jbutton("Edit/Open EDL for currently inserted DVD") do
    drive, volume_name, dvd_id = choose_dvd_drive_or_file true # require a real DVD disk :)
    edit_list_path = EdlParser.single_edit_list_matches_dvd(dvd_id)
    if edit_list_path
      open_file_to_edit_it edit_list_path
    else
      show_blocking_message_dialog "EDL for this dvd doesn't exist yet, maybe create it first? #{volume_name}"
    end
  end
  
  create_new_edl_for_current_dvd_text = "Create new Edit List for currently inserted DVD"
  @create_new_edl_for_current_dvd = new_jbutton(create_new_edl_for_current_dvd_text, 
      "If your DVD doesn't have an EDL created for it, this will be your first step--create an EDL file for it.")
  @create_new_edl_for_current_dvd.on_clicked do
   drive, volume_name, dvd_id = choose_dvd_drive_or_file true # require a real DVD disk :)
    edit_list_path = EdlParser.single_edit_list_matches_dvd(dvd_id, true)
    if edit_list_path
  if show_select_buttons_prompt('It appears that one or more EDL\'s exist for this DVD already--create another?', {}) == :no
      raise 'aborting'
  end
    end	  
    create_brand_new_dvd_edl
  	update_currently_inserted_dvd_list # notify them that files have changed...lodo is there a better way?
  end
  
  add_callback_for_dvd_edl_present { |disk_available, edl_available|
    #TODO rdp file buttons
    @open_current.set_enabled edl_available
    #@create_new_edl_for_current_dvd.set_enabled disk_available
    if edl_available
      @create_new_edl_for_current_dvd.text= create_new_edl_for_current_dvd_text + " [yours already has one!]"
    else
if disk_available
        @create_new_edl_for_current_dvd.text= create_new_edl_for_current_dvd_text + " [it doesn't have one yet!]"
else
  @create_new_edl_for_current_dvd.text= create_new_edl_for_current_dvd_text + " [no disk inserted!]"
end
    end
  }
  
  @parse_srt = new_jbutton("Scan a subtitle file (.srt) to detect profanity timestamps automatically" )
  @parse_srt.tool_tip = <<-EOL
    You can download a .srt file and use it to programmatically search for the location of various profanities.
    Basically download it from opensubtitles.org (or engsub.net et al),
    (for opensubtitles.org enter dvd title in the search box, click on a result, click one from the list with an English flag, 
    then choose 'Download(zip)', then unzip the file)
    NB that you'll want/need to *carefully* double check your subtitle file for accuracy. Here's how:
    Now carefully compare a beginning timestamp in it with the actual words in the .srt file 
    with the actual DVD.
    (see the button "Watch DVD unedited (realtime mplayer)")
    (smplayer can kind of do it, too, play it, hit the 'o' button to display
    the OSD timestamp, then go to just before the verbiage, 
    and hit the '.' key until a subtitle very first appears.
    Next convert that number to 29.97 fps (using the button for that).
  EOL

  @parse_srt.on_clicked do

    srt_filename = new_existing_file_selector_and_select_file("Pick srt file to scan for profanities [may need to download .srt file first]:", File.expand_path('~'))
  if(srt_filename =~ /utf16/) # from subrip sometimes
    show_blocking_message_dialog "warning--filename #{srt_filename} may be in utf16, which we don't yet parse"
                end
		if srt_filename =~ /\.sub$/i
show_blocking_message_dialog "warning--file has to be in Subrip [.srt] format, and yours might be in .sub format, which is incompatible"
		end
    # TODO nuke, or do I use them for the 600.0 stuff?
    add_to_beginning = "0.0"#get_user_input("How much time to subtract from the beginning of every subtitle entry (ex: (1:00,1:01) becomes (0:59,1:01))", "0.0")
    add_to_end = "0.0"#get_user_input("How much time to add to the end of every subtitle entry (ex: (1:00,1:04) becomes (1:00,1:05))", "0.0")
 
	if show_select_buttons_prompt("Sometimes subtitle files' time signatures don't match precisely with the video.\nWould you like to enter some information to allow it to synchronize the timestamps?\n  (on the final pass you should do this, even if it already matches well, for future information' sake)") == :yes
      euphemized_synchronized_entries = nil
      with_autoclose_message("parsing srt file... #{srt_filename}") do
        parsed_profanities, euphemized_synchronized_entries = SubtitleProfanityFinder.edl_output_from_string File.read(srt_filename), {},  0, 0, 0, 0, 3000, 3000
			write_subs_to_file euphemized_filename = get_temp_file_name('euphemized.subtitles.txt'), euphemized_synchronized_entries
    open_file_to_edit_it euphemized_filename
        sleep 0.5 # let it open in TextEdit/Notepad first...
  	    bring_to_front
      end

      if show_select_buttons_prompt("Would you like to start playing the movie in mplayer, to be able to search for subtitle timestamp times [you probably do...]?\n") == :yes
        show_blocking_message_dialog "ok--use the arrow keys and pgdown/pgup to search/scan, and then '.' to pinpoint a precise subtitle start time within mplayer.\nYou will be prompted for a beginning and starting timestamp time to search for."
        play_dvd_smplayer_unedited true
      end
      all_entries = euphemized_synchronized_entries

      all_entries.shift if all_entries[0].text =~ / by |downloaded/i # only place I think
      all_entries.pop if all_entries[-1].text =~ / by |downloaded/i

      display_and_raise "unable to parse subtitle file?" unless all_entries.size > 10
      
      start_text = all_entries[0].single_line_text
      start_srt_time = all_entries[0].beginning_time
      human_start = EdlParser.translate_time_to_human_readable(start_srt_time)
      start_movie_ts = get_user_input("Enter beginning timestamp within the movie itself for when the subtitle \"#{start_text}\"\nfirst frame the subtitle appears on the on screen display (possibly near #{human_start})", @start_movie_remember)
      @start_movie_remember = start_movie_ts
      start_movie_time = EdlParser.translate_string_to_seconds start_movie_ts
      if(show_select_buttons_prompt 'Would you like to select an ending timestamp at the end or 3/4 mark of the movie [end can be a spoiler at times]?', :yes => 'very end of movie', :no => '3/4 of the way into movie') == :yes
       end_entry = all_entries[-1]
      else
       end_entry = all_entries[all_entries.length*0.75] 
      end
      end_text = end_entry.single_line_text
      end_srt_time = end_entry.beginning_time
      human_end  = EdlParser.translate_time_to_human_readable(end_srt_time)
      end_movie_ts = get_user_input("Enter beginning timestamp within the movie itself for when the subtitle ##{end_entry.index_number}\n\"#{end_text}\"\nfirst appears (possibly near #{human_end}).\nYou can find it by searching to near that time in the movie [pgup+pgdown, then arrow keys], find some subtitle, then find where that subtitle is within the .srt file to see where it lies\nrelative to the one you are interested in\nthen seek relative to that to find the one you want.")
      end_movie_time = EdlParser.translate_string_to_seconds end_movie_ts
    else
   start_srt_time = 0
      start_movie_time = 0
      end_srt_time = 3000
      end_movie_time = 3000
	end

    parsed_profanities, euphemized_synchronized_entries = nil
    with_autoclose_message("parsing srt file... #{srt_filename}") do
      parsed_profanities, euphemized_synchronized_entries = SubtitleProfanityFinder.edl_output_from_string File.read(srt_filename), {}, add_to_beginning.to_f, add_to_end.to_f, start_srt_time, start_movie_time, end_srt_time, end_movie_time
    end
    
    filename = get_temp_file_name('partial.edl.txt')
    out =  "# copy and paste these into your \"mute\" section of A SEPARATE EDL already created with the other buttons, for lines you deem them mutable\n" + parsed_profanities
    out += %!\n\n#Also add these lines at the bottom of the EDL (for later coordination):\n"beginning_subtitle" => ["#{start_text}", "#{start_movie_ts}"],! +
           %!\n"ending_subtitle_entry" => ["#{end_text}", "#{end_movie_ts}"],!
    middle_entry = euphemized_synchronized_entries[euphemized_synchronized_entries.length*0.5]
    show_blocking_message_dialog "You may want to double check if the math worked out.\n\"#{middle_entry.single_line_text}\" (##{middle_entry.index_number})\nshould appear at #{EdlParser.translate_time_to_human_readable middle_entry.beginning_time}\nIf it's off much you may want to try a different .srt file"
    File.write filename, out
    open_file_to_edit_it filename
    sleep 1 # let it open
		
		if LocalStorage['prompt_obscure_options']
   if show_select_buttons_prompt("Would you like to write out a synchronized, euphemized .srt file [useful if you want to watch the movie with sanitized subtitles later]\nyou probably don't?") == :yes
        out_file = new_nonexisting_filechooser_and_go("Select filename to write to", File.dirname(srt_filename), File.basename(srt_filename)[0..-5] + ".euphemized.srt")
  write_subs_to_file out_file, euphemized_synchronized_entries
        show_in_explorer out_file
      end
		end
    
  end
	  
  add_text_line 'Create: Advanced View Edited Options'
  
  @mplayer_edl_with_subs = new_jbutton( "Watch DVD edited (realtime) (with mplayer, subtitles)") do
    watch_dvd_edited_realtime_mplayer true
  end
  
	  @mplayer_edl_with_subs.tool_tip="This watches it in mplayer, which has access to its console output, and also includes subtitles."
	  
  @mplayer_partial = new_jbutton( "Watch DVD edited (realtime) (mplayer) based on timestamp") do
    times = get_start_stop_times_strings
    times.map!{|t| EdlParser.translate_string_to_seconds t}
    start_time = times[0]
    end_time = times[1]
    extra_mplayer_commands = ["-ss #{start_time}", "-endpos #{end_time - start_time}"]
    play_smplayer_edl_non_blocking nil, extra_mplayer_commands, true, false, add_end = 0.0, add_begin = 0.0 # create mode => aggressive
  end
	  
	  @mplayer_partial.tool_tip="this can play just a specific portion of your film, like from second 30 to 35, for testing."
        
  new_jbutton("Display mplayer keyboard commands/howto/instructions") do
    show_mplayer_instructions
  end

  add_text_line "Create: Watch Unedited Options:"
  
  @play_smplayer = new_jbutton( "Watch DVD unedited (realtime smplayer)")
  @play_smplayer.tool_tip = <<-EOL
    This will play the DVD unedited within smplayer.
    NB it will default to title 1, so updated your EDL file that matches this DVD with the proper title if this doesn't work for you 
    i.e. if it just plays a single preview title or what not, and not the main title, you need to change this value.
    This is useful if you want to just kind of watch the movie to enjoy it, and look for scenes to cut out.
    You can use the built-in OSD (on-screen-display) to see what time frame the questionable scenes are at
    (type "o" to toggle it).  However, just realize that the OSD is in 30 fps, and our time stamps are all in 29.97
    fps, so you'll need to convert it (the convert timestamp button) to be able to use it in a file.
    NB That you can get the mplayer keyboard control instructions with the show instructions button.
  EOL
  @play_smplayer.on_clicked {
    play_dvd_smplayer_unedited false
  }

  add_text_line "Less commonly used Edit options:"

  new_jbutton("Create new Edit List (for netflix instant or movie file)") do # LODO VIDEO_TS here too?
 create_new_for_file_or_netflix
  end
  
  new_jbutton("Show more (rarely used) buttons/options") do
    child = new_child_window
    child.show_rarely_used_buttons
  end

end

#setup_default_buttonsObject



697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
# File 'lib/gui/base.rb', line 697

def setup_default_buttons
  if we_are_in_upconvert_mode
    add_play_upconvert_buttons
  else
    if we_are_in_create_mode
      setup_create_buttons
    else
      setup_normal_buttons
    end
  
  end # big else
  
  @exit = new_jbutton("Exit", "Exits the application and kills any background processes that are running at all--don't exit unless you are done processing all the way!")
  @exit.on_clicked {
    Thread.new { self.close } # don't waste the time to close it :P
    puts 'Thank you for using Sensible Cinema. Come again!'
    System.exit 0
  }

  increment_button_location
  increment_button_location
  self

end

#setup_normal_buttonsObject



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/gui/normal.rb', line 28

def setup_normal_buttons
  add_text_line ""
  
  @mplayer_edl = new_jbutton( watch_edited_text="Watch currently mounted DVD edited (realtime)" )
  @mplayer_edl.tool_tip = "This will watch your DVD in realtime from your computer while skipping/muting questionable scenes."
  @mplayer_edl.on_clicked {
    play_smplayer_edl_non_blocking
	sleep 5
	puts 'enjoy your movie playing in other window'
    sleep 1
	hard_exit if OS.doze? # paranoid on cpu usage LOL LODO mac too? it kills mplayer child processes currently...hmm...
  }
  
  add_callback_for_dvd_edl_present { |disk_available, edl_available|
    b = @mplayer_edl
 if disk_available
			if edl_available
 b.enable
 b.text=watch_edited_text
			else
 b.enable # leave it enabled in case it's some nonstandard form of a disk that does have one [?]
 b.text= watch_edited_text + "  [disk has no Edit List Available!]" 
			end
		else
@mplayer_edl.disable
@mplayer_edl.text=watch_edited_text + " [no disk presently inserted]"
		end
  }
  
  @watch_file_edl = new_jbutton( "Watch movie file edited (realtime)" ) do
    force_accept_file_style_license
    choose_file_and_edl_and_create_sxs_or_play false
  end
  
  @create = new_jbutton( "Create edited version of a file on Your Hard Drive" )
  @create.tool_tip = <<-EOL
    This takes a file and creates a new file on your hard disk like dvd_name_edited.mpg that you can watch when it's done.
    The file you create will contain the whole movie edited.
    It takes quite awhile maybe 2 hours.  Sometimes the progress bar will look paused--it typically continues eventually.
  EOL
  @create.on_clicked {
    force_accept_file_style_license
   check_for_file_manipulation_dependencies
    do_create_edited_copy_via_file false
  }
  
  if LocalStorage[UpConvertEnglish] # LODO no tight coupling like this
    add_text_line ''
    add_open_documentation_button
    @upconv_line = add_text_line "    #{get_current_upconvert_as_phrase}"
  else
    @upconv_line = add_text_line ''
    add_open_documentation_button
  end
  
  @show_upconvert_options = new_jbutton("Tweak Preferences [timing, upconversion]") do
 set_individual_preferences
    show_blocking_message_dialog "You will now be able to set some upconversion options, which makes the playback look nicer but uses more cpu [if desired].\nClose the window when finished."
    upconvert_window = new_child_window
    upconvert_window.add_change_upconvert_buttons
  end
  @show_upconvert_options.tool_tip= "Allows you to set your upconvert options.\nUpconverting attempts to playback your movie with higher quality on high resolution monitors."
  
  new_jbutton("Create new Edit Decision List") do
   window = new_child_window
    window.setup_create_buttons
 end
		
    @upload = new_jbutton("Feedback/submissions welcome!") # keeps this one last! :)
    @upload.tool_tip = "We welcome all feedback!\nQuestion, comments, request help.\nAlso if you create a new EDL, please submit it back to us so that others can benefit from it later!"
    @upload.on_clicked {
    show_blocking_message_dialog "ok, next it will open up the groups page now or optionally an email you could send"
      system_non_blocking("start mailto:[email protected]")
      system_non_blocking("start http://groups.google.com/group/sensible-cinema")
    }
    increment_button_location

	  
  @progress_bar = JProgressBar.new(0, 100)
  @progress_bar.set_bounds(44,@starting_button_y,@button_width,23)
  @progress_bar.visible = false
  @panel.add @progress_bar 
  add_text_line ""# spacing
end

#show_blocking_message_dialog(message, title = , style = JOptionPane::INFORMATION_MESSAGE) ⇒ Object



576
577
578
# File 'lib/gui/base.rb', line 576

def show_blocking_message_dialog(message, title = message.split("\n")[0], style= JOptionPane::INFORMATION_MESSAGE)
  SwingHelpers.show_blocking_message_dialog message, title, style
end

#show_copy_pastable_string(message, value) ⇒ Object



593
594
595
596
597
# File 'lib/gui/base.rb', line 593

def show_copy_pastable_string(message, value)
  bring_to_front
  RubyClip.set_clipboard value            
  get_user_input message + " (has been copied to clipboard)", value, true
end

#show_in_explorer(filename) ⇒ Object



599
600
601
# File 'lib/gui/base.rb', line 599

def show_in_explorer filename
  SwingHelpers.show_in_explorer filename
end

#show_mplayer_instructionsObject



511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
# File 'lib/gui/create.rb', line 511

def show_mplayer_instructions
  show_non_blocking_message_dialog <<-EOL
    About to run mplayer.  To control it (or smplayer), you can use these keyboard keys:
    spacebar : pause,
    double clicky/right click/'f' : toggle full screen,
    enter : select DVD menu currently highlighted
    arrow keys (left, right, up down, pg up, pg dn) : seek/scan
    / and *	: inc/dec volume.
    'o' key: turn on on-screen-display timestamps see wiki "understanding timestamps"
    'v' key: toggle display of subtitles.
    '.' key: step forward one frame.
    '#' key: change audio language track
    'j' : change subtitle track/language
	  [ and ] make playback faster or slower [like 2x]
  EOL
end

#show_non_blocking_message_dialog(message, close_button_text = 'Close') ⇒ Object

call dispose on this to close it if it hasn’t been canceled yet…



581
582
583
584
585
# File 'lib/gui/base.rb', line 581

def show_non_blocking_message_dialog message, close_button_text = 'Close'
  bring_to_front
  # lodo NonBlockingDialog it can get to the top instead of being so buried...
  SwingHelpers.show_non_blocking_message_dialog message, close_button_text
end

#show_rarely_used_buttonsObject



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/gui/create.rb', line 228

def show_rarely_used_buttons
  if we_are_in_developer_mode?
   @reload = new_jbutton("[programmer mode] reload bin/sensible-cinema code") do
     for file in Dir[__DIR__ + '/*.rb']
       p file
       eval(File.read(file), TOPLEVEL_BINDING, file)
     end
   end
  end

  @display_dvd_info = new_jbutton( "Display information about current DVD (ID, timing, etc.)" )
  @display_dvd_info.tool_tip = "This is useful to setup a DVD's 'unique ID' within an EDL for it. \nIf your EDL doesn't have a line like disk_unique_id => \"...\" then you will want to run this to be able to add that line in."
  @display_dvd_info.on_clicked {
    Thread.new {
      out_hashes, title_lengths = get_disk_info
     out_string = out_hashes.map{|name, value| name.inspect + ' => ' + value.inspect  + ','}.join("\n") + "\n" + title_lengths.join("\n")
      out_string += %!\n"timestamps_relative_to" => ["dvd_start_offset","29.97"],! # since they're all this way currently
      filename = get_temp_file_name('disk_info.txt')
      File.write filename, out_string 
      open_file_to_edit_it filename
      out_string # for unit tests :) TODO
    }
  }
  
  @convert_seconds_to_ts = new_jbutton( "Convert 3600.0 <-> 1:00:00 style timestamps" )
  @convert_seconds_to_ts.on_clicked {
    input = get_user_input("Enter \"from\" timestamp, like 3600 or 1:40:00:", "1:00:00.1 or 3600.1")
    while(input)
      if input =~ /:/
        output = EdlParser.translate_string_to_seconds input
        output = "%.02f" % output # so they know we're not rounding for example 6.10 not 6.1
      else
        output = EdlParser.translate_time_to_human_readable input.to_f, true
      end 
      input = show_copy_pastable_string("Converted:", output)         
    end
  }
  
  @convert_timestamp = new_jbutton( "Convert timestamp from DVD player time to EDL time (30->29.97 fps)" )
  @convert_timestamp.tool_tip=<<-EOL
    Our EDL's assume 29.97 fps (which is what a DVD actually has).  Unfortunately most hardware or commercial DVD players
    think that the DVD is 30 fps, which means that if you use them for timestamps for your EDL's,
    you will be slightly off (at the end of a 2 hour film, by 8 seconds).  So all your edits will be wrong.
    How to fix: convert your times from "DVD player" time to "EDL accurate" time by using this button.
    This is necessary for all hardware DVD player timestamps, PowerDVD player (software), Windows Media Player (playing a DVD), 
    and mplayer's "on screen display" DVD timestamps.
    It is not necessary for smplayer timestamps (or mplayer's "V: 3600" in the command line), which are already 29.97.
    smplayer's on-screen-display (the 'o' key) is accurate (and doesn't suffer from MPEG timestamps resets midway through) 
    but is 30 fps, so timestamps would need to be converted.
    Dont use VLC for DVD timestamps at all--it can get up to 30s off!  VLC playing back a file is usually pretty accurate to 29.97.
    In general, GUI's like VLC or smplayer are always a tidge off (maybe 0.3s) from the right timestamp, so take that into consideration.
    Mplayers "V: 3600" is usually right on (29.97 fps), however.
  EOL
  @convert_timestamp.on_clicked {
    thirty_fps = get_user_input("Enter your DVD/hardware (30 fps) timestamp, I'll convert it to 29.97 (usable in EDL's):", "1:00:00.1")
    thirty_fps_in_seconds = EdlParser.translate_string_to_seconds thirty_fps
    twenty_nine_seven_fps = ConvertThirtyFps.from_thirty(thirty_fps_in_seconds)
    human_twenty_nine_seven = EdlParser.translate_time_to_human_readable twenty_nine_seven_fps, true
    show_copy_pastable_string("Sensible cinema usable value (29.97 fps) for #{thirty_fps} would be:                ", human_twenty_nine_seven)
  }
  
  @create_dot_edl = new_jbutton( "Create a side-by-side moviefilename.edl file [XBMC etc.]")
  @create_dot_edl.tool_tip = <<-EOL
    Creates a moviefilename.edl file (corresponding to some moviefilename.some_ext file already existing)
    XBMC/smplayer (smplayer can be used by WMC plugins, etc.) "automagically detect", 
    if it exists, and automatically use it .edl to show that file edited played back.
    If you use smplayer, note that you'll need to download the "lord mulder mplayer"
    version (which includes an updated version of mplayer that fixes some bugs in EDL playback)
  EOL
  @create_dot_edl.on_clicked {
    show_blocking_message_dialog "Warning: With XBMC you'll need at least Eden v11.0 for mutes to work at all"
    choose_file_and_edl_and_create_sxs_or_play true
  }
	  
  add_text_line 'Options for creating an edited movie file from a local file:'
  
  new_jbutton("Show options to help with creating a fully edited movie file") do
    window = new_child_window
    window.add_options_that_use_local_files
  end
  
	  
  if LocalStorage['have_zoom_button']
    @create_zoomplayer = new_jbutton( "Create a ZoomPlayer MAX compatible EDL file") do
      raise unless OS.doze?
      @prompt ||= show_blocking_message_dialog <<-EOL
  To work with ZoomPlayer MAX's scene cut functionality, first play the DVD you want to watch edited, and 
  create a dummy cut for it in it via the ZoomPlayer MAX cut scene editor. (right click -> open interface -> scene cut editor)
  Once you create a cut, ZoomPlayer will create a file like this:
  [windows 7]: c:\\Users\\All Users\\Zoom Player\\DVD-Bookmarks\\Sintel_NTSC.3D4D1DFBEB1A53FE\\disc.cut
  
  After it has been created, come back to this.  You will next be prompted to select the generated disc.cut file, and also a sensible cinema EDL file.
  The generated file will then be overwritten with the sensible cinema EDL information.
  DVD compatible only currently--ask if you want it for file based selection as well and I can add it.
      EOL
      zoom_path  = new_existing_file_selector_and_select_file( "Pick Zoomplayer disc.cut File to override", ENV["ALLUSERSPROFILE"]+ '/Zoom Player/DVD-Bookmarks' )
      edl_path = new_existing_file_selector_and_select_file( "Pick EDL", EdlParser::EDL_DIR)
      specs = parse_edl(edl_path)
      require_relative '../zoom_player_max_edl'
      out = ZoomPlayerMaxEdl.convert_to_edl_string specs
      File.write(zoom_path, out)
      show_blocking_message_dialog "wrote #{zoom_path}"
    end
  end
end

#show_select_buttons_prompt(message, names = {}) ⇒ Object



603
604
605
# File 'lib/gui/base.rb', line 603

def show_select_buttons_prompt message, names ={}
  SwingHelpers.show_select_buttons_prompt(message, names)
end

#system_blocking(command, low_prio = false) ⇒ Object



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/gui/base.rb', line 361

def system_blocking command, low_prio = false
  return true if command =~ /^@rem/ # JRUBY-5890 bug
  if low_prio
    out = IO.popen(command) # + " 2>&1"
    low_prio = 64 # from msdn
    
    if command =~ /(ffmpeg|mencoder)/
      # XXXX not sure if there's a better way...because some *are* complex and have ampersands...
      # unfortunately have to check for nil because it could exit too early [?]
      exe_name = $1 + '.exe'
      begin
        p = proc{ ole = ::WMI::Win32_Process.find(:first,  :conditions => {'Name' => exe_name}); sleep 1 unless ole; ole }
        piddy = p.call || p.call || p.call # we actually do need this to loop...guess we're too quick
        # but the first time through this still inexplicably fails all 3...odd
        piddys = ::WMI::Win32_Process.find(:all,  :conditions => {'Name' => exe_name})
        for piddy in piddys
          # piddy.SetPriority low_prio # this call can seg fault at times...JRUBY-5422
          pid = piddy.ProcessId # this doesn't seg fault, tho
          system_original("vendor\\setpriority -lowest #{pid}") # uses PID for the command line
        end
      rescue Exception => e
        p 'warning, got exception trying to set priority [jruby prob? ...]', e
      end
    end
    print out.read # let it finish
    out.close
    $?.exitstatus == 0 # 0 means success
  else
    raise command + " failed env #{ENV['PATH']}" unless system_original command
  end
end

#system_non_blocking(command) ⇒ Object



393
394
395
# File 'lib/gui/base.rb', line 393

def system_non_blocking command
  @background_thread = Thread.new { system_original command }
end

#upconvert_set_to_anything?Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/gui/upconvert.rb', line 46

def upconvert_set_to_anything?
  LocalStorage[UpConvertEnglish].present?
end

#update_currently_inserted_dvd_listObject



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/gui/base.rb', line 126

def update_currently_inserted_dvd_list
 present_discs = []
  DriveInfo.get_dvd_drives_as_openstruct.each{|disk|
    if disk.VolumeName
       dvd_id = DriveInfo.md5sum_disk(disk.MountPoint)			     
       edit_list_path_if_present = EdlParser.single_edit_list_matches_dvd(dvd_id, true)
    if edit_list_path_if_present
         human_name = parse_edl(edit_list_path_if_present)['name']
      human_name ||= ''
       end
       present_discs << [human_name, disk.VolumeName, edit_list_path_if_present]
    end
  }
  found_one = false
  present_discs.map!{|human_name, volume_name, has_edl| 
    if human_name
      found_one = true
      "DVD: #{human_name} has an Edit List available! (#{volume_name})"
    else
      "DVD: (#{volume_name}) has NO Edit List available!"
    end
  }
  if present_discs.length > 0
    @current_dvds_line1.text= '      ' + present_discs[0]
    @current_dvds_line2.text= '      ' + present_discs[1..2].join(" ")
  else
    @current_dvds_line1.text= '      No DVD discs currently inserted.'
    @current_dvds_line2.text = ''
  end
  @callbacks_for_dvd_edl_present.each{|c| c.call(present_discs.length > 0, found_one)}
end

#warn_if_no_upconvert_options_currently_selectedObject



61
62
63
64
65
66
67
# File 'lib/gui/upconvert.rb', line 61

def warn_if_no_upconvert_options_currently_selected
  if !upconvert_set_to_anything?
    show_non_blocking_message_dialog "Warning: upconvert options have not been set yet--set upconvert options first, if desired."
  else
    JFrame.new # something it can call dispose on :P
  end
end

#watch_dvd_edited_realtime_mplayer(show_subs) ⇒ Object



373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/gui/create.rb', line 373

def watch_dvd_edited_realtime_mplayer show_subs
  edl_out_command = ""
  if LocalStorage['prompt_obscure_options']
    answer = show_select_buttons_prompt <<-EOL, {}
      Would you like to create an .edl outfile as it plays (hit button to capture timestamps)?
      EOL
    if answer == :yes
      show_non_blocking_message_dialog <<-EOL
      EDL outfile:
      As mplayer goes through the video, when you see a scene you want to edit or skip, 
      hit 'i' and mplayer will write the start time in the file and set it to skip for 2 seconds, 
      hit 'i' again to end the edited/skipped scene, within that file.
      EOL
  
      edlout_filename = new_nonexisting_filechooser_and_go "pick edlout filename"
      edl_out_command = "-edlout #{edlout_filename}"
      
    else
      @has_ever_rejected_edl_outfile = true
    end
  end
  thred = play_smplayer_edl_non_blocking nil, [edl_out_command], true, false, add_end = 0.0, add_begin = 0.0, show_subs # more aggressive :)
  if(edl_out_command.present?)
    open_edl_file_when_done thred, edlout_filename
  end
end

#we_are_in_create_modeObject



173
174
175
# File 'lib/gui/base.rb', line 173

def we_are_in_create_mode
 @args.index("--create-mode")
end

#we_are_in_developer_mode?Boolean

Returns:

  • (Boolean)


177
178
179
# File 'lib/gui/base.rb', line 177

def we_are_in_developer_mode?
  @args.detect{|a| a == '--developer-mode'}
end

#we_are_in_upconvert_modeObject



693
694
695
# File 'lib/gui/base.rb', line 693

def we_are_in_upconvert_mode
  @args.index("--upconvert-mode")
end

#when_thread_done(thread) ⇒ Object



211
212
213
# File 'lib/gui/base.rb', line 211

def when_thread_done(thread)
  Thread.new {thread.join; yield }
end

#with_autoclose_message(message) ⇒ Object



687
688
689
690
691
# File 'lib/gui/base.rb', line 687

def with_autoclose_message(message)
  a = show_non_blocking_message_dialog message
  yield
  a.close
end

#write_subs_to_file(out_file, euphemized_synchronized_entries) ⇒ Object



215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/gui/create.rb', line 215

def write_subs_to_file out_file, euphemized_synchronized_entries
     File.open(out_file, 'w') do |f|
       euphemized_synchronized_entries.each_with_index{|entry, idx|
         beginning_time = EdlParser.translate_time_to_human_readable(entry.beginning_time).gsub('.',',')
         ending_time = EdlParser.translate_time_to_human_readable(entry.ending_time).gsub('.',',')
         f.puts entry.index_number
         f.puts "#{beginning_time} --> #{ending_time}"
         f.puts entry.text
         f.puts ''
       }
		  end
end