# Homepage: <http://handbrake.m0k.org/>.
# It may be used under the terms of the GNU General Public License.
-# This script parses HandBrake's Mac presets into hashes, which can be displayed in various formats for use by the CLI and various wrappers.
+# This script parses HandBrake's Mac presets into hashes, which can
+# be displayed in various formats for use by the CLI and its wrappers.
# For handling command line arguments to the script
require 'optparse'
require 'ostruct'
+# CLI options: (code based on http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/index.html )
+def readOptions
+
+ # --[no-]cli-raw, -r gives raw CLI for wiki
+ # --cli-parse, -p gives CLI strings for wrappers
+ # --api, -a gives preset code for test.c
+ # --api-list, -A gives CLI strings for --preset-list display
+ # --[no-]header, -h turns off banner display
+ options = OpenStruct.new
+ options.cliraw = false
+ options.cliparse = false
+ options.api = false
+ options.apilist = false
+ options.header = false
+
+ opts = OptionParser.new do |opts|
+ opts.banner = "Usage: manicure.rb [options]"
+
+ opts.separator ""
+ opts.separator "Options:"
+
+ opts.on("-r", "--cli-raw", "Gives example strings for the HB wiki") do |raw|
+ options.cliraw = raw
+ option_set = true
+ end
+
+ opts.on("-p", "--cli-parse", "Gives presets as wrapper-parseable CLI", " option strings") do |par|
+ options.cliparse = par
+ end
+
+ opts.on("-a", "--api", "Gives preset code for test.c") do |api|
+ options.api = api
+ end
+
+ opts.on("-A", "--api-list", "Gives code for test.c's --preset-list", " options") do |alist|
+ options.apilist = alist
+ end
+
+ opts.on("-H", "--Header", "Display a banner before each preset") do |head|
+ options.header = head
+ end
+
+ opts.on_tail("-h", "--help", "Show this message") do
+ puts opts
+ exit
+ end
+ end.parse!
+
+ return options
+
+end
+
# These arrays contain all the other presets and hashes that are going to be used.
# Yeah, they're global variables. In an object-oriented scripting language.
# Real smooth, huh?
-$presetMasterList = []
-$hashMasterList = []
-# This class is pretty much everything. It contains multitudes.
-class PresetClass
+# This class parses the user's presets .plist into an array of hashes
+class Presets
- # A width of 40 gives nice, compact output.
- @@columnWidth=40
+ attr_reader :hashMasterList
# Running initialization runs everything.
# Calling it will also call the parser
# and display output.
- def initialize(options)
+ def initialize
- @options = options
-
# Grab input from the user's presets .plist
rawPresets = readPresetPlist
# Now it's time to use that info to store each
# preset individually, in the master list.
+ @presetMasterList = []
i = 0
while i <= presetBreaks.size
if i == 0 #first preset
# Grab the stew, up to the 1st offset.
- $presetMasterList[i] = presetStew.slice(0..presetBreaks[i].to_i)
+ @presetMasterList[i] = presetStew.slice(0..presetBreaks[i].to_i)
elsif i < presetBreaks.size #middle presets
# Grab the stew from the last offset to the current..
- $presetMasterList[i] = presetStew.slice(presetBreaks[i-1].to_i..presetBreaks[i].to_i)
+ @presetMasterList[i] = presetStew.slice(presetBreaks[i-1].to_i..presetBreaks[i].to_i)
else #final preset
# Grab the stew, starting at the last offset, all the way to the end.
- $presetMasterList[i] = presetStew.slice(presetBreaks[i-1].to_i..presetStew.length)
+ @presetMasterList[i] = presetStew.slice(presetBreaks[i-1].to_i..presetStew.length)
end
i += 1
end
# Parse the presets into hashes
+ @hashMasterList = []
+
buildPresetHash
- # Print to screen.
- displayCommandStrings
end
def readPresetPlist # Grab the .plist and store it in presets
return presetBreaks
end
- def buildPresetHash #fill up $hashMasterList with hashes of all key/value pairs
+ def buildPresetHash #fill up @hashMasterList with hashes of all key/value pairs
j = 0
# Iterate through all presets, treating each in turn as singleServing
- $presetMasterList.each do |singleServing|
-
+ @presetMasterList.each do |singleServing|
+
+ # Initialize the hash for preset j (aka singleServing)
+ @hashMasterList[j] = Hash.new
+
# Each key and value are on sequential lines.
# Iterating through by twos, use that to build a hash.
# Each key, on line i, paired with its value, on line i+1
- tempHash = Hash.new
i = 1
while i < singleServing.length
- tempHash[singleServing[i]] = singleServing[i+1]
+ @hashMasterList[j].store( singleServing[i], singleServing[i+1] )
i += 2
end
-
- # Now store that hash in the master list.
- $hashMasterList[j]=tempHash
-
+
j += 1
end
end
+end
+
+# This class displays the presets to stdout in various formats.
+class Display
+
+
+ def initialize(hashMasterList, options)
+
+ @hashMasterList = hashMasterList
+ @options = options
+
+ # A width of 40 gives nice, compact output.
+ @columnWidth=40
+
+ # Print to screen.
+ displayCommandStrings
+
+ end
+
def displayCommandStrings # prints everything to screen
# Iterate through the hashes.
- $hashMasterList.each do |hash|
+ @hashMasterList.each do |hash|
# Check to make there are valid contents
if hash.key?("PresetName")
def displayHeader(hash) # A distinct banner to separate each preset
# Print a line of asterisks
- puts "*" * @@columnWidth
+ puts "*" * @columnWidth
# Print the name, centered
- puts '* '+hash["PresetName"].to_s.center(@@columnWidth-4)+' *'
+ puts '* '+hash["PresetName"].to_s.center(@columnWidth-4)+' *'
# Print a line of dashes
- puts '~' * @@columnWidth
+ puts '~' * @columnWidth
# Print the description, centered and word-wrapped
- puts hash["PresetDescription"].to_s.center(@@columnWidth).gsub(/\n/," ").scan(/\S.{0,#{@@columnWidth-2}}\S(?=\s|$)|\S+/)
+ puts hash["PresetDescription"].to_s.center(@columnWidth).gsub(/\n/," ").scan(/\S.{0,#{@columnWidth-2}}\S(?=\s|$)|\S+/)
# Print another line of dashes
- puts '~' * @@columnWidth
+ puts '~' * @columnWidth
# Print the formats the preset uses
- puts "#{hash["FileCodecs"]}".center(@@columnWidth)
+ puts "#{hash["FileCodecs"]}".center(@columnWidth)
# Note if the preset isn't built-in
if hash["Type"].to_i == 1
- puts "Custom Preset".center(@@columnWidth)
+ puts "Custom Preset".center(@columnWidth)
end
# Note if the preset is marked as default.
if hash["Default"].to_i == 1
- puts "This is your default preset.".center(@@columnWidth)
+ puts "This is your default preset.".center(@columnWidth)
end
# End with a line of tildes.
- puts "~" * @@columnWidth
+ puts "~" * @columnWidth
end
#Video encoder
if hash["VideoEncoder"] != "FFmpeg"
commandString << " -e "
- if hash["VideoEncoder"] == "x264 (h.264 Main)"
- commandString << "x264"
- elsif hash["VideoEncoder"] == "x264 (h.264 iPod)"
- commandString << "x264b30"
- else
- commandString << hash["VideoEncoder"].to_s.downcase
- end
+ commandString << hash["VideoEncoder"].to_s.downcase
end
#VideoRateControl
#Audio encoder (only specifiy bitrate and samplerate when not doing AC-3 pass-thru)
commandString << " -E "
case hash["FileCodecs"]
- when /AC-3/
+ when /AAC + AC3 Audio/
+ commandString << "aac+ac3"
+ when /AC-3 /
commandString << "ac3"
- when /AAC/
+ when /AAC Audio/
commandString << "faac" << " -B " << hash["AudioBitRate"] << " -R " << hash["AudioSampleRate"]
when /Vorbis/
commandString << "vorbis" << " -B " << hash["AudioBitRate"] << " -R " << hash["AudioSampleRate"]
commandString << "mkv"
end
+ #iPod MP4 atom
+ if hash["Mp4iPodCompatible"].to_i == 1
+ commandString << " -I"
+ end
+
+ # 64-bit files
+ if hash["Mp4LargeFile"].to_i == 1
+ commandString << " -4"
+ end
+
#Cropping
if !hash["PictureAutoCrop"].to_i
commandString << " --crop "
# That's it, print to screen now
puts commandString
- #puts "*" * @@columnWidth
+ #puts "*" * @columnWidth
puts "\n"
end
#Video encoder
if hash["VideoEncoder"] != "FFmpeg"
commandString << " -e "
- if hash["VideoEncoder"] == "x264 (h.264 Main)"
- commandString << "x264"
- elsif hash["VideoEncoder"] == "x264 (h.264 iPod)"
- commandString << "x264b30"
- else
- commandString << hash["VideoEncoder"].to_s.downcase
- end
+ commandString << hash["VideoEncoder"].to_s.downcase
end
#VideoRateControl
#Audio encoder (only include bitrate and samplerate when not doing AC3 passthru)
commandString << " -E "
case hash["FileCodecs"]
+ when /AC3 Audio/
+ commandString << "aac+ac3"
when /AC-3/
commandString << "ac3"
- when /AAC/
+ when /AAC Audio/
commandString << "faac" << " -B " << hash["AudioBitRate"] << " -R " << hash["AudioSampleRate"]
when /Vorbis/
commandString << "vorbis" << " -B " << hash["AudioBitRate"] << " -R " << hash["AudioSampleRate"]
commandString << "mkv"
end
+ #iPod MP4 atom
+ if hash["Mp4iPodCompatible"].to_i == 1
+ commandString << " -I"
+ end
+
+ # 64-bit files
+ if hash["Mp4LargeFile"].to_i == 1
+ commandString << " -4"
+ end
+
#Cropping
if !hash["PictureAutoCrop"].to_i
commandString << " --crop "
# That's it, print to screen now
puts commandString
- #puts "*" * @@columnWidth
+ #puts "*" * @columnWidth
puts "\n"
end
commandString << "mux = " << "HB_MUX_MKV;\n "
end
+ #iPod MP4 atom
+ if hash["Mp4iPodCompatible"].to_i == 1
+ commandString << "job->ipod_atom = 1;\n "
+ end
+
+ # 64-bit files
+ if hash["Mp4LargeFile"].to_i == 1
+ commandString << "job->largeFileSize = 1;\n"
+ end
+
#Video encoder
if hash["VideoEncoder"] != "FFmpeg"
commandString << "vcodec = "
- if hash["VideoEncoder"] == "x264 (h.264 Main)"
+ if hash["VideoEncoder"] == "x264"
commandString << "HB_VCODEC_X264;\n "
- elsif hash["VideoEncoder"] == "x264 (h.264 iPod)"
- commandString << "HB_VCODEC_X264;\njob->h264_level = 30;\n "
elsif hash["VideoEncoder"].to_s.downcase == "xvid"
commandString << "HB_VCODEC_XVID;\n "
end
#Audio encoder
commandString << "acodec = "
case hash["FileCodecs"]
- when /AAC/
+ when /AC3 Audio/
+ commandString << "HB_ACODEC_FAAC;\n "
+ commandString << "audio_mixdown = HB_AMIXDOWN_DOLBYPLII_AC3;\n "
+ commandString << "arate = 48000;\n "
+ when /AAC Audio/
commandString << "HB_ACODEC_FAAC;\n "
when /AC-3/
commandString << "HB_ACODEC_AC3;\n "
commandString << "deinterlace_opt = \"-1\";\n "
when 2
commandString << "deinterlace = 1;\n "
- commandString << "deinterlace_opt = \"0\";\n "
+ commandString << "deinterlace_opt = \"2\";\n "
when 3
commandString << "deinterlace = 1;\n "
- commandString << "deinterlace_opt = \"2:-1:1\";\n "
+ commandString << "deinterlace_opt = \"0\";\n "
when 4
commandString << "deinterlace = 1;\n "
commandString << "deinterlace_opt = \"1:-1:1\";\n "
# That's it, print to screen now
puts commandString
- #puts "*" * @@columnWidth
+ #puts "*" * @columnWidth
puts "\n"
end
#Video encoder
if hash["VideoEncoder"] != "FFmpeg"
commandString << " -e "
- if hash["VideoEncoder"] == "x264 (h.264 Main)"
- commandString << "x264"
- elsif hash["VideoEncoder"] == "x264 (h.264 iPod)"
- commandString << "x264b30"
- else
- commandString << hash["VideoEncoder"].to_s.downcase
- end
+ commandString << hash["VideoEncoder"].to_s.downcase
end
#VideoRateControl
#Audio encoder
commandString << " -E "
case hash["FileCodecs"]
- when /AAC/
+ when /AC3 Audio/
+ commandString << "aac+ac3"
+ when /AAC Audio/
commandString << "faac"
when /AC-3/
commandString << "ac3"
commandString << "mkv"
end
+ #iPod MP4 atom
+ if hash["Mp4iPodCompatible"].to_i == 1
+ commandString << " -I"
+ end
+
+ # 64-bit files
+ if hash["Mp4LargeFile"].to_i == 1
+ commandString << " -4"
+ end
+
#Cropping
if !hash["PictureAutoCrop"].to_i
commandString << " --crop "
puts commandString
puts "\n"
end
+
end
-# CLI options: (code based on http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/index.html )
-# --[no-]cli-raw, -r gives raw CLI for wiki
-# --cli-parse, -p gives CLI strings for wrappers
-# --api, -a gives preset code for test.c
-# --api-list, -A gives CLI strings for --preset-list display
-# --[no-]header, -h turns off banner display
-options = OpenStruct.new
-options.cliraw = false
-options.cliparse = false
-options.api = false
-options.apilist = false
-options.header = false
-
-opts = OptionParser.new do |opts|
- opts.banner = "Usage: manicure.rb [options]"
-
- opts.separator ""
- opts.separator "Options:"
-
- opts.on("-r", "--cli-raw", "Gives example strings for the HB wiki") do |r|
- options.cliraw = r
- option_set = true
- end
-
- opts.on("-p", "--cli-parse", "Gives presets as wrapper-parseable CLI", " option strings") do |p|
- options.cliparse = p
- end
-
- opts.on("-a", "--api", "Gives preset code for test.c") do |api|
- options.api = api
- end
-
- opts.on("-A", "--api-list", "Gives code for test.c's --preset-list", " options") do |A|
- options.apilist = A
- end
-
- opts.on("-H", "--Header", "Display a banner before each preset") do |H|
- options.header = H
- end
-
- opts.on_tail("-h", "--help", "Show this message") do
- puts opts
- exit
- end
-end.parse!
+# First grab the specified CLI options
+options = readOptions
# Only run if one of the useful CLI flags have been passed
if options.cliraw == true || options.cliparse == true || options.api == true || options.apilist == true
- # This line is the ignition.
- PresetClass.new(options)
+ # This line is the ignition -- generates hashes of
+ # presets and then displays them to the screen
+ # with the options the user selects on the CLI.
+ Display.new( Presets.new.hashMasterList, options )
else
# Direct the user to the help
puts "\n\tUsage: manicure.rb [options]"