#!/usr/bin/ruby # so my editor will like the file...
=begin
Copyright 2010, Roger Pack
This file is part of Sensible Cinema.
Sensible Cinema is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Sensible Cinema is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Sensible Cinema. If not, see .
=end
alias system_original system
require 'fileutils'
class String
def snake_case
self.gsub(/::/, '/').
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
tr("-", "_").
downcase
end
def quotify
'"' + self + '"'
end
end
# a few I'll always need no matter what...
require_relative '../jruby-swing-helpers/swing_helpers'
require_relative '../jruby-swing-helpers/storage'
require_relative '../edl_parser'
require 'tmpdir'
require 'whichr'
require 'os'
if OS.doze?
autoload :WMI, 'ruby-wmi'
autoload :EightThree, './lib/eight_three'
end
# attempt to load on demand...i.e. faster...
for kls in [:MencoderWrapper, :MplayerEdl, :PlayAudio, :SubtitleProfanityFinder, :ConvertThirtyFps]
autoload kls, "./lib/#{kls.to_s.snake_case}"
end
for kls in [:PlayAudio, :RubyClip, :DriveInfo]
autoload kls, "./lib/jruby-swing-helpers/#{kls.to_s.snake_case}"
end
if OS.windows?
vendor_cache = File.expand_path(File.dirname(__FILE__)) + '/../../vendor/cache'
for name in ['.', 'mencoder', 'ffmpeg', 'mplayer_edl']
# put them all before the old path
ENV['PATH'] = (vendor_cache + '/' + name).to_filename + ';' + ENV['PATH']
end
installed_smplayer_folders = Dir['{c,d,e,f,g}:/program files*/smplayer']
for folder in installed_smplayer_folders
ENV['PATH'] = ENV['PATH'] + ";#{folder.gsub('/', "\\")}"
end
else
# handled in check_mac_installed.rb file
end
import 'javax.swing.ImageIcon'
module SensibleSwing
include SwingHelpers # various swing classes
JFrame
VERSION = File.read(File.dirname(__FILE__) + "/../../VERSION").strip
puts "v. " + VERSION
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()) #
class MainWindow < JFrame
include SwingHelpers # work-around?
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
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
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
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
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
def we_are_in_create_mode
@args.index("--create-mode")
end
def we_are_in_developer_mode?
@args.detect{|a| a == '--developer-mode'}
end
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
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
def increment_button_location how_much = 30
@starting_button_y += how_much
setSize @button_width+80, @starting_button_y + 50
end
LocalStorage = Storage.new("sensible_cinema_storage_#{VERSION}")
def when_thread_done(thread)
Thread.new {thread.join; yield }
end
# a window that when closed doesn't bring the whole app down
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
def run_smplayer_non_blocking *args
@background_thread = Thread.new {
run_smplayer_blocking *args
}
end
# basically run mplayer/smplayer on a file or DVD
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
SMPlayerIniFile = File.expand_path("~/.smplayer_sensible_cinema/smplayer.ini")
LocalModifiedMplayer = File.expand_path "vendor/cache/mplayer_edl/mplayer.exe"
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...
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
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
def system_non_blocking command
@background_thread = Thread.new { system_original command }
end
# force them choose which system call to use explicitly
if respond_to? :system
undef system
else # it's a reload
end
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
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
if OS.doze? # avoids spaces in filenames :)
EdlTempFile = EightThree.convert_path_to_8_3(Dir.tmpdir) + '\\mplayer.edl' # stay 8.3 friendly :)
else
raise if Dir.tmpdir =~ / / # that would be unexpected, and possibly cause problems...
EdlTempFile = Dir.tmpdir + '/mplayer.temp.edl'
end
EdlFilesChosen = {} # allow for switching tapes but still cache EDL loc. :P
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
LocalStorage.set_default('mplayer_beginning_buffer', 0.5)
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
# MplayerBeginingBuffer = 1.0
# MplayerEndBuffer = 0.0
def begin_buffer_preference
LocalStorage['mplayer_beginning_buffer']
end
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
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
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
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
# also caches directory previously selected ...
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
def show_blocking_message_dialog(message, title = message.split("\n")[0], style= JOptionPane::INFORMATION_MESSAGE)
SwingHelpers.show_blocking_message_dialog message, title, style
end
# call dispose on this to close it if it hasn't been canceled yet...
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
java_import javax.swing.UIManager
def get_user_input(message, default = '', cancel_ok = false)
SwingHelpers.get_user_input message, default, cancel_ok
end
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
def show_in_explorer filename
SwingHelpers.show_in_explorer filename
end
def show_select_buttons_prompt message, names ={}
SwingHelpers.show_select_buttons_prompt(message, names)
end
def parse_edl path
EdlParser.parse_file path
end
def get_freespace path
JFile.new(File.dirname(path)).get_usable_space
end
def get_drive_with_most_space_with_slash
DriveInfo.get_drive_with_most_space_with_slash
end
attr_accessor :background_thread, :buttons
NonDvd = 'non dvd has no dvdid' # we need it for convenience, say you want to go through your indexed vids and convert them all?
# returns e:\, volume_name, dvd_id
# or full_path.mkv, filename, ''
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
def display_and_raise error_message
show_blocking_message_dialog error_message
raise error_message
end
def with_autoclose_message(message)
a = show_non_blocking_message_dialog message
yield
a.close
end
def we_are_in_upconvert_mode
@args.index("--upconvert-mode")
end
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
def get_disk_chooser_window names
DropDownSelector.new(self, names, "Click to select DVD drive")
end
def get_temp_file_name name_with_ext
File.dirname(EdlTempFile) + '/' + name_with_ext
end
# converts to full path, 8.3 if on doze
def normalize_path path
path = File.expand_path path
path = EightThree.convert_path_to_8_3 path if OS.doze?
end
end
end
class ::File
def self.get_root_dir this_path
this_path = File.expand_path this_path
if OS.doze?
this_path[0..2]
else
this_path.split('/')[0]
end
end
def self.strip_drive_windows this_complete_path
if OS.doze?
this_complete_path[2..-1]
else
this_complete_path
end
end
end
class ::String
def just_letters
gsub(/[^a-z0-9]/i, '').downcase
end
end