OSDN Git Service

Add preset override for anamorphic to manicure
[handbrake-jp/handbrake-jp-git.git] / scripts / manicure.rb
1 #! /usr/bin/ruby
2 # manincure.rb version 0.66
3
4 # This file is part of the HandBrake source code.
5 # Homepage: <http://handbrake.m0k.org/>.
6 # It may be used under the terms of the GNU General Public License.
7
8 # This script parses HandBrake's Mac presets into hashes, which can
9 # be displayed in various formats for use by the CLI and its wrappers.
10
11 # For handling command line arguments to the script
12 require 'optparse'
13 require 'ostruct'
14 require 'rubygems'
15 require 'plist'
16
17 # CLI options: (code based on http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/index.html )
18 def readOptions
19   
20   # --[no-]cli-raw, -r gives raw CLI for wiki
21   # --cli-parse, -p gives CLI strings for wrappers
22   # --api, -a gives preset code for test.c
23   # --api-list, -A gives CLI strings for --preset-list display
24   # --[no-]header, -h turns off banner display
25   options = OpenStruct.new
26   options.cliraw = false
27   options.cliparse = false
28   options.api = false
29   options.apilist = false
30   options.header = false
31   
32   opts = OptionParser.new do |opts|
33     opts.banner = "Usage: manicure.rb [options]"
34     
35     opts.separator ""
36     opts.separator "Options:"
37     
38     opts.on("-r", "--cli-raw", "Gives example strings for the HB wiki") do |raw|
39       options.cliraw = raw
40       option_set = true
41     end
42     
43     opts.on("-p", "--cli-parse", "Gives presets as wrapper-parseable CLI", " option strings") do |par|
44       options.cliparse = par
45     end
46     
47     opts.on("-a", "--api", "Gives preset code for test.c") do |api|
48       options.api = api
49     end
50     
51     opts.on("-A", "--api-list", "Gives code for test.c's --preset-list", " options") do |alist|
52       options.apilist = alist
53     end
54     
55     opts.on("-H", "--Header", "Display a banner before each preset") do |head|
56       options.header = head
57     end
58     
59     opts.on_tail("-h", "--help", "Show this message") do
60         puts opts
61         exit
62     end
63   end.parse!
64   
65   return options
66   
67 end
68
69 # These arrays contain all the other presets and hashes that are going to be used.
70 # Yeah, they're global variables. In an object-oriented scripting language.
71 # Real smooth, huh?
72
73 # This class parses the user's presets .plist into an array of hashes
74 class Presets
75   
76   attr_reader :hashMasterList
77   
78   # Running initialization runs everything.
79   # Calling it will also call the parser
80   # and display output.
81   def initialize
82     
83    # Grab the user's home path
84    homeLocation = `echo $HOME`.chomp
85    
86    # Use that to build a path to the presets .plist
87    #inputFile = homeLocation+'/Library/Application Support/HandBrake/UserPresets.plist'
88    inputFile = homeLocation+'/UserPresets.plist'
89    
90     # Parse the presets into hashes
91     @hashMasterList = Plist::parse_xml( inputFile )
92     
93   end
94
95 end
96
97 # This class displays the presets to stdout in various formats.
98 class Display
99   
100   def initialize(hashMasterList, options)
101   
102     @hashMasterList = hashMasterList
103     @options = options
104
105     # A width of 40 gives nice, compact output.
106     @columnWidth=40
107     
108     # Print to screen.
109     displayCommandStrings
110     
111   end
112   
113   def displayCommandStrings # prints everything to screen
114     
115     # Iterate through the hashes.    
116     @hashMasterList.each do |hash|
117     
118       # Check to see whether we've got a preset or afolder
119       if !hash["Folder"]
120         # It's a top-level preset
121        displayIndividualPreset(hash, 0) 
122       else
123         # It's a folder, yay
124         displayFolder( hash, 0 )
125         hash["ChildrenArray"].each do |subhash|
126           # Drill down to see its contents
127           if !subhash["Folder"]
128             # It's a preset
129             displayIndividualPreset(subhash, 1)
130           else
131             # It's a folder
132             displayFolder( subhash, 1 )
133             subhash["ChildrenArray"].each do |subsubhash|
134               # At this point we're far enough down we won't try to drill further
135               if !subsubhash["Folder"]
136                 displayIndividualPreset(subsubhash, 2)
137               end
138             end
139             displayFolderCloser( 1 )
140           end
141         end
142         displayFolderCloser( 0 )
143       end
144     end
145   end
146   
147   def displayIndividualPreset(hash, depth)
148     if @options.header == true
149       # First throw up a header to make each preset distinct
150       displayHeader(hash)
151     end
152     
153     if @options.cliraw == true
154       # Show the preset's full CLI string equivalent
155       generateCLIString(hash, depth)
156     end
157     
158     if @options.cliparse == true
159       generateCLIParse(hash, depth)
160     end
161     
162     if @options.api == true
163       # Show the preset as code for test/test.c, HandBrakeCLI
164       generateAPIcalls(hash)
165     end
166     
167     if @options.apilist == true
168       # Show the preset as print statements, for CLI wrappers to parse.
169       generateAPIList(hash, depth) 
170     end
171   end
172   
173   def displayHeader(hash) # A distinct banner to separate each preset
174     
175     # Print a line of asterisks
176     puts "*" * @columnWidth
177     
178     # Print the name, centered
179     puts '* '+hash["PresetName"].to_s.center(@columnWidth-4)+' *'
180     
181     # Print a line of dashes
182     puts '~' * @columnWidth
183     
184     # Print the description, centered and word-wrapped
185     puts hash["PresetDescription"].to_s.center(@columnWidth).gsub(/\n/," ").scan(/\S.{0,#{@columnWidth-2}}\S(?=\s|$)|\S+/)
186     
187     # Print another line of dashes
188     puts '~' * @columnWidth
189     
190     # Print the formats the preset uses
191     puts "#{hash["FileCodecs"]}".center(@columnWidth)
192     
193     # Note if the preset isn't built-in
194     if hash["Type"] == 1
195       puts "Custom Preset".center(@columnWidth)
196     end
197
198     # Note if the preset is marked as default.
199     if hash["Default"] == 1
200       puts "This is your default preset.".center(@columnWidth)
201     end
202     
203     # End with a line of tildes.  
204     puts "~" * @columnWidth
205     
206   end
207   
208   def displayFolder( hash, depth )
209
210     if @options.cliraw == true
211       # Show the folder's full in a format that matches the CLI equivalents
212       generateCLIFolderString(hash, depth)
213     end
214     
215     if @options.cliparse == true
216       # Show the folder in a format that matches the CLI wrapper equivalents
217       generateCLIFolderParse(hash, depth)
218     end
219     
220     if @options.apilist == true
221       # Show the folder as print statements, for CLI wrappers to parse.
222       generateAPIFolderList(hash, depth) 
223     end
224     
225   end
226   
227   def displayFolderCloser( depth )
228     if @options.cliraw == true
229       # Show the folder's full in a format that matches the CLI equivalents
230       generateCLIFolderCloserString( depth )
231     end
232     
233     if @options.cliparse == true
234       # Show the folder in a format that matches the CLI wrapper equivalents
235       generateCLIFolderCloserParse( depth )
236     end
237     
238     if @options.apilist == true
239       # Show the folder as print statements, for CLI wrappers to parse.
240       generateAPIFolderCloserList( depth ) 
241     end
242   end
243   
244   def generateCLIFolderString( hash, depth ) # Shows the folder for the CLI equivalents
245     commandString = ""
246     depth.times do
247       commandString << "   "
248     end
249     (depth+1).times do
250       commandString << "<"
251     end
252     commandString << " " << hash["PresetName"] << "\n\n"
253     puts commandString
254   end
255   
256   def generateCLIFolderCloserString( depth )
257     commandString = ""
258     depth.times do
259       commandString << "   "
260     end
261     (depth+1).times do
262       commandString << ">"
263     end
264     commandString << "\n\n"
265     puts commandString
266   end
267   
268   def generateCLIString(hash, depth) # Makes a full CLI equivalent of a preset
269     commandString = ""
270     depth.times do
271       commandString << "   "
272     end
273     commandString << './HandBrakeCLI -i DVD -o ~/Movies/movie.'
274     
275     #Filename suffix
276     case hash["FileFormat"]
277     when /MP4/
278       commandString << "mp4 "
279     when /MKV/
280       commandString << "mkv "
281     end
282     
283     #Video encoder
284     if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
285       commandString << " -e "
286       case hash["VideoEncoder"]
287       when /x264/
288         commandString << "x264"
289       when /Theora/
290         commandString << "theora"
291       end
292     end
293
294     #VideoRateControl
295     case hash["VideoQualityType"]
296     when 0
297       commandString << " -S " << hash["VideoTargetSize"]
298     when 1
299       commandString << " -b " << hash["VideoAvgBitrate"]
300     when 2
301       commandString << " -q " << hash["VideoQualitySlider"].to_s
302     end
303
304     #FPS
305     if hash["VideoFramerate"] != "Same as source"
306       if hash["VideoFramerate"] == "23.976 (NTSC Film)"
307         commandString << " -r " << "23.976"
308       elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
309         commandString << " -r " << "29.97"
310       elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
311         commandString << " -r " << "25"
312       else
313         commandString << " -r " << hash["VideoFramerate"]
314       end
315     end
316     
317     #Audio tracks
318     audioBitrates = ""
319     audioEncoders = ""
320     audioMixdowns = ""
321     audioSamplerates = ""
322     audioTracks = ""
323     audioTrackDRCs = ""
324     audioCount = hash["AudioList"].size
325     
326     hash["AudioList"].each do |audioTrack|
327       audioCount = audioCount - 1
328
329       #Bitrates
330       audioBitrates << audioTrack["AudioBitrate"]
331       
332       #Encoders
333       case audioTrack["AudioEncoder"]
334         when /AC3 /
335           audioEncoders << "ac3"
336         when /AAC/
337           audioEncoders << "faac"
338         when /Vorbis/
339           audioEncoders << "vorbis"
340         when /MP3/
341           audioEncoders << "lame"
342       end
343       
344       #Mixdowns
345       case audioTrack["AudioMixdown"]
346       when /Mono/
347         audioMixdowns << "mono"
348       when /Stereo/
349         audioMixdowns << "stereo"
350       when /Dolby Surround/
351         audioMixdowns << "dpl1"
352       when /Dolby Pro Logic II/
353         audioMixdowns << "dpl2"
354       when /discrete/
355         audioMixdowns << "6ch"
356       when /Passthru/
357         audioMixdowns << "auto"
358       end
359       
360       #Samplerates
361       audioSamplerates << audioTrack["AudioSamplerate"]
362       
363       #Tracks
364       audioTracks << audioTrack["AudioTrack"].to_s
365       
366       #DRC
367       audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
368       
369       if audioCount > 0
370         audioBitrates << ","
371         audioEncoders << ","
372         audioMixdowns << ","
373         audioSamplerates << ","
374         audioTracks << ","
375         audioTrackDRCs << ","
376       end
377       
378     end
379     commandString << " -a " << audioTracks
380     commandString << " -E " << audioEncoders
381     commandString << " -B " << audioBitrates
382     commandString << " -6 " << audioMixdowns
383     commandString << " -R " << audioSamplerates
384     commandString << " -D " << audioTrackDRCs
385         
386     #Container
387     commandString << " -f "
388     case hash["FileFormat"]
389     when /MP4/
390       commandString << "mp4"
391     when /MKV/
392       commandString << "mkv"
393     end
394     
395     #iPod MP4 atom
396     if hash["Mp4iPodCompatible"].to_i == 1
397       commandString << " -I"
398     end
399     
400     # 64-bit files
401     if hash["Mp4LargeFile"] == 1
402       commandString << " -4"
403     end
404     
405     #Cropping
406     if hash["PictureAutoCrop"] == 0
407       commandString << " --crop "
408       commandString << hash["PictureTopCrop"].to_s
409       commandString << ":"
410       commandString << hash["PictureBottomCrop"].to_s
411       commandString << ":"
412       commandString << hash["PictureLeftCrop"].to_s
413       commandString << ":"
414       commandString << hash["PictureRightCrop"].to_s
415     end
416     
417     #Dimensions
418     if hash["PictureWidth"] != 0
419       commandString << " -X "
420       commandString << hash["PictureWidth"].to_s
421     end
422     if hash["PictureHeight"] != 0
423       commandString << " -Y "
424       commandString << hash["PictureHeight"].to_s
425     end
426     
427     #Subtitles
428     if hash["Subtitles"] && hash["Subtitles"] != "None"
429       if hash["Subtitles"] == "Autoselect"
430         commandString << " --subtitle-scan"
431       else
432         commandString << " -s "
433         commandString << hash["Subtitles"]
434       end
435     end
436
437     #Video Filters
438     if hash["UsesPictureFilters"] == 1
439       
440       case hash["PictureDeinterlace"]
441       when 2
442         commandString << " --deinterlace=\"fast\""
443       when 3
444         commandString << " --deinterlace=\slow\""
445       when 4
446         commandString << " --deinterlace=\"slower\""
447       when 5
448         commandString << " --deinterlace=\"slowest\""
449       end
450       
451       case hash["PictureDenoise"]
452       when 2
453         commandString << " --denoise=\"weak\""
454       when 3
455         commandString << " --denoise=\"medium\""
456       when 4
457         commandString << " --denoise=\"strong\""
458       end
459       
460       if hash["PictureDetelecine"] == 2 then commandString << " --detelecine" end
461       if hash["PictureDeblock"] != 0 then commandString << " --deblock=" << hash["PictureDeblock"].to_s end
462       if hash["PictureDecomb"] == 2 then commandString << " --decomb" end
463       
464     end
465     
466     #Anamorphic
467     if hash["PicturePAR"] == 1
468       commandString << " --strict-anamorphic"
469     elsif hash["PicturePAR"] == 2
470       commandString << " --loose-anamorphic"
471     elsif hash["PicturePAR"] == 3
472       commandString << " --custom-anamorphic"
473     end
474
475     #Booleans
476     if hash["ChapterMarkers"] == 1 then commandString << " -m" end
477     if hash["VideoGrayScale"] == 1 then commandString << " -g" end
478     if hash["VideoTwoPass"] == 1 then commandString << " -2" end
479     if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end
480
481     #x264 Options
482     if hash["x264Option"] != ""
483       commandString << " -x "
484       commandString << hash["x264Option"]
485     end
486     
487     # That's it, print to screen now
488     puts commandString
489     
490     #puts "*" * @columnWidth
491
492     puts  "\n"
493   end
494   
495   def generateCLIFolderParse( hash, depth ) # Shows the folder for wrappers to parse
496     commandString = ""
497     depth.times do
498       commandString << "   "
499     end
500     (depth+1).times do
501       commandString << "<"
502     end
503     commandString << " " << hash["PresetName"] << "\n\n"
504     puts commandString
505   end
506   
507   def generateCLIFolderCloserParse( depth )
508     commandString = ""
509     depth.times do
510       commandString << "   "
511     end
512     (depth+1).times do
513       commandString << ">"
514     end
515     commandString << "\n\n"
516     puts commandString
517   end
518   
519   def generateCLIParse(hash, depth) # Makes a CLI equivalent of all user presets, for wrappers to parse
520     commandString = ""
521     depth.times do
522       commandString << "   "
523     end
524     commandString << '+ ' << hash["PresetName"] << ":"
525         
526     #Video encoder
527     if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
528       commandString << " -e "
529       case hash["VideoEncoder"]
530       when /x264/
531         commandString << "x264"
532       when /Theora/
533         commandString << "theora"
534       end
535     end
536
537     #VideoRateControl
538     case hash["VideoQualityType"]
539     when 0
540       commandString << " -S " << hash["VideoTargetSize"]
541     when 1
542       commandString << " -b " << hash["VideoAvgBitrate"]
543     when 2
544       commandString << " -q " << hash["VideoQualitySlider"].to_s
545     end
546
547     #FPS
548     if hash["VideoFramerate"] != "Same as source"
549       if hash["VideoFramerate"] == "23.976 (NTSC Film)"
550         commandString << " -r " << "23.976"
551       elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
552         commandString << " -r " << "29.97"
553       elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
554         commandString << " -r " << "25"
555       else
556         commandString << " -r " << hash["VideoFramerate"]
557       end
558     end
559     
560     #Audio tracks
561     audioBitrates = ""
562     audioEncoders = ""
563     audioMixdowns = ""
564     audioSamplerates = ""
565     audioTracks = ""
566     audioTrackDRCs = ""
567     audioCount = hash["AudioList"].size
568     
569     hash["AudioList"].each do |audioTrack|
570       audioCount = audioCount - 1
571
572       #Bitrates
573       audioBitrates << audioTrack["AudioBitrate"]
574       
575       #Encoders
576       case audioTrack["AudioEncoder"]
577         when /AC3 /
578           audioEncoders << "ac3"
579         when /AAC/
580           audioEncoders << "faac"
581         when /Vorbis/
582           audioEncoders << "vorbis"
583         when /MP3/
584           audioEncoders << "lame"
585       end
586       
587       #Mixdowns
588       case audioTrack["AudioMixdown"]
589       when /Mono/
590         audioMixdowns << "mono"
591       when /Stereo/
592         audioMixdowns << "stereo"
593       when /Dolby Surround/
594         audioMixdowns << "dpl1"
595       when /Dolby Pro Logic II/
596         audioMixdowns << "dpl2"
597       when /discrete/
598         audioMixdowns << "6ch"
599       when /Passthru/
600         audioMixdowns << "auto"
601       end
602       
603       #Samplerates
604       audioSamplerates << audioTrack["AudioSamplerate"]
605       
606       #Tracks
607       audioTracks << audioTrack["AudioTrack"].to_s
608       
609       #DRC
610       audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
611       
612       if audioCount > 0
613         audioBitrates << ","
614         audioEncoders << ","
615         audioMixdowns << ","
616         audioSamplerates << ","
617         audioTracks << ","
618         audioTrackDRCs << ","
619       end
620       
621     end
622     commandString << " -a " << audioTracks
623     commandString << " -E " << audioEncoders
624     commandString << " -B " << audioBitrates
625     commandString << " -6 " << audioMixdowns
626     commandString << " -R " << audioSamplerates
627     commandString << " -D " << audioTrackDRCs
628     
629     #Container
630     commandString << " -f "
631     case hash["FileFormat"]
632     when /MP4/
633       commandString << "mp4"
634     when /MKV/
635       commandString << "mkv"
636     end
637     
638     #iPod MP4 atom
639     if hash["Mp4iPodCompatible"].to_i == 1
640       commandString << " -I"
641     end
642     
643     # 64-bit files
644     if hash["Mp4LargeFile"] == 1
645       commandString << " -4"
646     end
647     
648     #Cropping
649     if hash["PictureAutoCrop"] == 0
650       commandString << " --crop "
651       commandString << hash["PictureTopCrop"].to_s
652       commandString << ":"
653       commandString << hash["PictureBottomCrop"].to_s
654       commandString << ":"
655       commandString << hash["PictureLeftCrop"].to_s
656       commandString << ":"
657       commandString << hash["PictureRightCrop"].to_s
658     end
659     
660     #Dimensions
661     if hash["PictureWidth"] != 0
662       commandString << " -X "
663       commandString << hash["PictureWidth"].to_s
664     end
665     if hash["PictureHeight"] != 0
666       commandString << " -Y "
667       commandString << hash["PictureHeight"].to_s
668     end
669     
670     #Subtitles
671     if hash["Subtitles"] && hash["Subtitles"] != "None"
672       if hash["Subtitles"] == "Autoselect"
673         commandString << " --subtitle-scan"
674       else
675         commandString << " -s "
676         commandString << hash["Subtitles"]
677       end
678     end
679     
680     #Video Filters
681     if hash["UsesPictureFilters"] == 1
682       
683       case hash["PictureDeinterlace"]
684       when 2
685         commandString << " --deinterlace=\"fast\""
686       when 3
687         commandString << " --deinterlace=\slow\""
688       when 4
689         commandString << " --deinterlace=\"slower\""
690       when 5
691         commandString << " --deinterlace=\"slowest\""
692       end
693       
694       case hash["PictureDenoise"]
695       when 2
696         commandString << " --denoise=\"weak\""
697       when 3
698         commandString << " --denoise=\"medium\""
699       when 4
700         commandString << " --denoise=\"strong\""
701       end
702       
703       if hash["PictureDetelecine"] == 2 then commandString << " --detelecine" end
704       if hash["PictureDeblock"] != 0 then commandString << " --deblock=" << hash["PictureDeblock"].to_s end
705       if hash["PictureDecomb"] == 2 then commandString << " --decomb" end
706     end
707
708     #Anamorphic
709     if hash["PicturePAR"] == 1
710       commandString << " --strict-anamorphic"
711     elsif hash["PicturePAR"] == 2
712       commandString << " --loose-anamorphic"
713     elsif hash["PicturePAR"] == 3
714       commandString << " --custom-anamorphic"
715     end
716     
717     #Booleans
718     if hash["ChapterMarkers"] == 1 then commandString << " -m" end
719     if hash["VideoGrayScale"] == 1 then commandString << " -g" end
720     if hash["VideoTwoPass"] == 1 then commandString << " -2" end
721     if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end
722
723     #x264 Options
724     if hash["x264Option"] != ""
725       commandString << " -x "
726       commandString << hash["x264Option"]
727     end
728     
729     # That's it, print to screen now
730     puts commandString
731     
732     #puts "*" * @columnWidth
733
734     puts  "\n"
735   end
736
737   def generateAPIcalls(hash) # Makes a C version of the preset ready for coding into the CLI
738     
739     commandString = "if (!strcmp(preset_name, \"" << hash["PresetName"] << "\"))\n{\n    "
740     
741     #Filename suffix
742     commandString << "if( !mux )\n    "
743     commandString << "{\n    "
744
745     case hash["FileFormat"]
746     when /MP4/
747       commandString << "    mux = " << "HB_MUX_MP4;\n    "
748     when /MKV/
749       commandString << "    mux = " << "HB_MUX_MKV;\n    "
750     end
751     commandString << "}\n    "
752     
753     #iPod MP4 atom
754     if hash["Mp4iPodCompatible"].to_i == 1
755       commandString << "job->ipod_atom = 1;\n    "
756     end
757     
758     # 64-bit files
759     if hash["Mp4LargeFile"] == 1
760       commandString << "job->largeFileSize = 1;\n    "
761     end
762     
763     #Video encoder
764     if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
765       commandString << "vcodec = "
766       case hash["VideoEncoder"]
767       when /x264/
768         commandString << "HB_VCODEC_X264;\n    "
769       when /Theora/
770         commandString << "HB_VCODEC_THEORA;\n    "        
771       end
772     end
773
774     #VideoRateControl
775     case hash["VideoQualityType"]
776     when 0
777       commandString << "size = " << hash["VideoTargetSize"] << ";\n    "
778     when 1
779       commandString << "job->vbitrate = " << hash["VideoAvgBitrate"] << ";\n    "
780     when 2
781       commandString << "job->vquality = " << hash["VideoQualitySlider"].to_s << ";\n    "
782     end
783
784     #FPS
785     if hash["VideoFramerate"] != "Same as source"
786       if hash["VideoFramerate"] == "23.976 (NTSC Film)"
787         commandString << "job->vrate_base = " << "1126125;\n    "
788       elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
789         commandString << "job->vrate_base = " << "900900;\n    "
790       elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
791         commandString << "job->vrate_base = " << "1080000\n    "
792       # Gotta add the rest of the framerates for completion's sake.
793       end
794       commandString << "job->cfr = 1;\n    "
795     end
796     
797     #Audio tracks
798     audioBitrates = ""
799     audioEncoders = ""
800     audioMixdowns = ""
801     audioSamplerates = ""
802     audioTracks = ""
803     audioTrackDRCs = ""
804     audioCount = hash["AudioList"].size
805
806     hash["AudioList"].each do |audioTrack|
807       audioCount = audioCount - 1
808
809       #Bitrates
810       audioBitrates << audioTrack["AudioBitrate"]
811
812       #Encoders
813       case audioTrack["AudioEncoder"]
814         when /AC3 /
815           audioEncoders << "ac3"
816         when /AAC/
817           audioEncoders << "faac"
818         when /Vorbis/
819           audioEncoders << "vorbis"
820         when /MP3/
821           audioEncoders << "lame"
822       end
823
824       #Mixdowns
825       case audioTrack["AudioMixdown"]
826       when /Mono/
827         audioMixdowns << "mono"
828       when /Stereo/
829         audioMixdowns << "stereo"
830       when /Dolby Surround/
831         audioMixdowns << "dpl1"
832       when /Dolby Pro Logic II/
833         audioMixdowns << "dpl2"
834       when /discrete/
835         audioMixdowns << "6ch"
836       when /Passthru/
837         audioMixdowns << "auto"
838       end
839
840       #Samplerates
841       audioSamplerates << audioTrack["AudioSamplerate"]
842
843       #Tracks
844       audioTracks << audioTrack["AudioTrack"].to_s
845
846       #DRC
847       audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
848
849       if audioCount > 0
850         audioBitrates << ","
851         audioEncoders << ","
852         audioMixdowns << ","
853         audioSamplerates << ","
854         audioTracks << ","
855         audioTrackDRCs << ","
856       end
857
858     end
859     commandString << "if( !atracks )\n    "
860     commandString << "{\n    "
861     commandString << "    atracks = strdup(\"" << audioTracks
862     commandString << "\");\n    "
863     commandString << "}\n    "
864
865     commandString << "if( !acodecs )\n    "
866     commandString << "{\n    "
867     commandString << "    acodecs = strdup(\"" << audioEncoders
868     commandString << "\");\n    "
869     commandString << "}\n    "
870
871     commandString << "if( !abitrates )\n    "
872     commandString << "{\n    "
873     commandString << "    abitrates = strdup(\"" << audioBitrates
874     commandString << "\");\n    "
875     commandString << "}\n    "
876
877     commandString << "if( !mixdowns )\n    "
878     commandString << "{\n    "
879     commandString << "    mixdowns = strdup(\"" << audioMixdowns
880     commandString << "\");\n    "
881     commandString << "}\n    "
882
883     commandString << "if( !arates )\n    "
884     commandString << "{\n    "
885     commandString << "    arates = strdup(\"" << audioSamplerates
886     commandString << "\");\n    "
887     commandString << "}\n    "
888
889     commandString << "if( !dynamic_range_compression )\n    "
890     commandString << "{\n    "
891     commandString << "    dynamic_range_compression = strdup(\"" << audioTrackDRCs
892     commandString << "\");\n    "
893     commandString << "}\n    "
894     
895     #Cropping
896     if hash["PictureAutoCrop"] == 0
897       commandString << "job->crop[0] = " << hash["PictureTopCrop"].to_s << ";\n    "
898       commandString << "job->crop[1] = " << hash["PictureBottomCrop"].to_s << ";\n    "
899       commandString << "job->crop[2] = " << hash["PictureLeftCrop"].to_s << ";\n    "
900       commandString << "job->crop[4] = " << hash["PictureRightCrop"].to_s << ";\n    "
901     end
902     
903     #Dimensions
904     if hash["PictureWidth"] != 0
905       commandString << "maxWidth = "
906       commandString << hash["PictureWidth"].to_s << ";\n    "
907     end
908     if hash["PictureHeight"] != 0
909       commandString << "maxHeight = "
910       commandString << hash["PictureHeight"].to_s << ";\n    "
911     end
912     
913     #Subtitles
914     if hash["Subtitles"] != "None"
915       if hash["Subtitles"] == "Autoselect"
916         commandString << "subtitle_scan = 1;\n    "
917       else
918         commandString << "job->subtitle = "
919         commandString << ( hash["Subtitles"].to_i - 1).to_s << ";\n    "
920       end
921     end
922     
923     #x264 Options
924     if hash["x264Option"] != ""
925       commandString << "if( !x264opts )\n    "
926       commandString << "{\n    "
927       commandString << "    x264opts = strdup(\""
928       commandString << hash["x264Option"] << "\");\n    "
929       commandString << "}\n    "
930     end
931     
932     #Video Filters
933     if hash["UsesPictureFilters"] == 1
934       
935       case hash["PictureDeinterlace"]
936       when 2
937         commandString << "deinterlace = 1;\n    "
938         commandString << "deinterlace_opt = \"-1\";\n    "
939       when 3
940         commandString << "deinterlace = 1;\n    "
941         commandString << "deinterlace_opt = \"2\";\n    "
942       when 4
943         commandString << "deinterlace = 1;\n    "
944         commandString << "deinterlace_opt = \"0\";\n    "
945       when 5
946         commandString << "deinterlace = 1;\n    "
947         commandString << "deinterlace_opt = \"1:-1:1\";\n    "
948       end
949       
950       case hash["PictureDenoise"]
951       when 2
952         commandString << "denoise = 1;\n    "
953         commandString << "denoise_opt = \"2:1:2:3\";\n    "
954       when 3
955         commandString << "denoise = 1;\n    "
956         commandString << "denoise_opt = \"3:2:2:3\";\n    "
957       when 4
958         commandString << "denoise = 1;\n    "
959         commandString << "denoise_opt = \"7:7:5:5\";\n    "
960       end
961       
962       if hash["PictureDetelecine"] == 2 then commandString << "detelecine = 1;\n    " end
963       if hash["PictureDeblock"] != 0
964         then
965           commandString << "deblock = 1;\n    "
966           commandString << "deblock_opt = \"" << hash["PictureDeblock"].to_s << "\";\n    "
967         end
968       if hash["PictureDecomb"] == 2 then commandString << "decomb = 1;\n    " end
969       
970     end
971     
972     #Anamorphic
973     if hash["PicturePAR"] != 0
974       commandString << "if( !anamorphic_mode )\n    "
975       commandString << "{\n    "
976       if hash["PicturePAR"] == 1
977         commandString << "    anamorphic_mode = 1;\n    "
978       elsif hash["PicturePAR"] == 2
979         commandString << "    anamorphic_mode = 2;\n    "
980       elsif hash["PicturePAR"] == 3
981         commandString << "    anamorphic_mode = 3;\n    "
982       end
983       commandString << "}\n    "
984     end
985     
986     #Booleans
987     if hash["ChapterMarkers"] == 1 then commandString << "job->chapter_markers = 1;\n    " end
988     if hash["VideoGrayScale"] == 1 then commandString << "job->grayscale = 1;\n    " end
989     if hash["VideoTwoPass"] == 1 then commandString << "twoPass = 1;\n    " end
990     if hash["VideoTurboTwoPass"] == 1 then commandString << "turbo_opts_enabled = 1;\n" end
991     commandString << "\n"
992     commandString << "}"
993     
994     # That's it, print to screen now
995     puts commandString
996     #puts "*" * @columnWidth
997     puts  "\n"
998   end
999   
1000   def generateAPIFolderList( hash, depth )
1001     commandString = ""
1002     
1003     commandString << "    printf(\"\\n"
1004     depth.times do
1005       commandString << "   "
1006     end
1007     (depth+1).times do
1008       commandString << "<"
1009     end
1010     commandString << " " << hash["PresetName"]
1011     commandString << "\\n\");\n\n"    
1012     puts commandString
1013   end
1014   
1015   def generateAPIFolderCloserList( depth )
1016     commandString = ""
1017     
1018     commandString << "    printf(\"\\n"
1019     depth.times do
1020       commandString << "   "
1021     end
1022     (depth+1).times do
1023       commandString << ">"
1024     end
1025     commandString << "\\n\");\n\n"    
1026     puts commandString
1027   end
1028   
1029   def generateAPIList(hash, depth) # Makes a list of the CLI options a built-in CLI preset uses, for wrappers to parse
1030     commandString = ""
1031     commandString << "    printf(\"\\n"
1032     depth.times do
1033       commandString << "   "
1034     end
1035            
1036     commandString << "+ " << hash["PresetName"] << ": "
1037         
1038     #Video encoder
1039     if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
1040       commandString << " -e "
1041       case hash["VideoEncoder"]
1042       when /x264/
1043         commandString << "x264 "
1044       when /Theora/
1045         commandString << "theora "
1046       end
1047     end
1048
1049     #VideoRateControl
1050     case hash["VideoQualityType"]
1051     when 0
1052       commandString << " -S " << hash["VideoTargetSize"]
1053     when 1
1054       commandString << " -b " << hash["VideoAvgBitrate"]
1055     when 2
1056       commandString << " -q " << hash["VideoQualitySlider"].to_s
1057     end
1058
1059     #FPS
1060     if hash["VideoFramerate"] != "Same as source"
1061       if hash["VideoFramerate"] == "23.976 (NTSC Film)"
1062         commandString << " -r " << "23.976"
1063       elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
1064         commandString << " -r " << "29.97"
1065       elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
1066         commandString << " -r " << "25"
1067       else
1068         commandString << " -r " << hash["VideoFramerate"]
1069       end
1070     end
1071     
1072     #Audio tracks
1073     audioBitrates = ""
1074     audioEncoders = ""
1075     audioMixdowns = ""
1076     audioSamplerates = ""
1077     audioTracks = ""
1078     audioTrackDRCs = ""
1079     audioCount = hash["AudioList"].size
1080     
1081     hash["AudioList"].each do |audioTrack|
1082       audioCount = audioCount - 1
1083
1084       #Bitrates
1085       audioBitrates << audioTrack["AudioBitrate"]
1086       
1087       #Encoders
1088       case audioTrack["AudioEncoder"]
1089         when /AC3 /
1090           audioEncoders << "ac3"
1091         when /AAC/
1092           audioEncoders << "faac"
1093         when /Vorbis/
1094           audioEncoders << "vorbis"
1095         when /MP3/
1096           audioEncoders << "lame"
1097       end
1098       
1099       #Mixdowns
1100       case audioTrack["AudioMixdown"]
1101       when /Mono/
1102         audioMixdowns << "mono"
1103       when /Stereo/
1104         audioMixdowns << "stereo"
1105       when /Dolby Surround/
1106         audioMixdowns << "dpl1"
1107       when /Dolby Pro Logic II/
1108         audioMixdowns << "dpl2"
1109       when /discrete/
1110         audioMixdowns << "6ch"
1111       when /Passthru/
1112         audioMixdowns << "auto"
1113       end
1114       
1115       #Samplerates
1116       audioSamplerates << audioTrack["AudioSamplerate"]
1117       
1118       #Tracks
1119       audioTracks << audioTrack["AudioTrack"].to_s
1120       
1121       #DRC
1122       audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
1123       
1124       if audioCount > 0
1125         audioBitrates << ","
1126         audioEncoders << ","
1127         audioMixdowns << ","
1128         audioSamplerates << ","
1129         audioTracks << ","
1130         audioTrackDRCs << ","
1131       end
1132       
1133     end
1134     commandString << " -a " << audioTracks
1135     commandString << " -E " << audioEncoders
1136     commandString << " -B " << audioBitrates
1137     commandString << " -6 " << audioMixdowns
1138     commandString << " -R " << audioSamplerates
1139     commandString << " -D " << audioTrackDRCs
1140     
1141     #Container
1142     commandString << " -f "
1143     case hash["FileFormat"]
1144     when /MP4/
1145       commandString << "mp4"
1146     when /MKV/
1147       commandString << "mkv"
1148     end
1149     
1150     #iPod MP4 atom
1151     if hash["Mp4iPodCompatible"].to_i == 1
1152       commandString << " -I"
1153     end
1154     
1155     # 64-bit files
1156     if hash["Mp4LargeFile"] == 1
1157       commandString << " -4"
1158     end
1159     
1160     #Cropping
1161     if hash["PictureAutoCrop"] == 0
1162       commandString << " --crop "
1163       commandString << hash["PictureTopCrop"].to_s
1164       commandString << ":"
1165       commandString << hash["PictureBottomCrop"].to_s
1166       commandString << ":"
1167       commandString << hash["PictureLeftCrop"].to_s
1168       commandString << ":"
1169       commandString << hash["PictureRightCrop"].to_s
1170     end
1171     
1172     #Dimensions
1173     if hash["PictureWidth"] != 0
1174       commandString << " -X "
1175       commandString << hash["PictureWidth"].to_s
1176     end
1177     if hash["PictureHeight"] != 0
1178       commandString << " -Y "
1179       commandString << hash["PictureHeight"].to_s
1180     end
1181     
1182     #Subtitles
1183     if hash["Subtitles"] && hash["Subtitles"] != "None"
1184       if hash["Subtitles"] == "Autoselect"
1185         commandString << " --subtitle-scan"
1186       else
1187         commandString << " -s "
1188         commandString << hash["Subtitles"]
1189       end
1190     end
1191     
1192     #Video Filters
1193     if hash["UsesPictureFilters"] == 1
1194       
1195       case hash["PictureDeinterlace"]
1196       when 2
1197         commandString << " --deinterlace=\\\"fast\\\""
1198       when 3
1199         commandString << " --deinterlace=\\\slow\\\""
1200       when 4
1201         commandString << " --deinterlace=\\\"slower\\\""
1202       when 5
1203         commandString << " --deinterlace=\\\"slowest\\\""
1204       end
1205       
1206       case hash["PictureDenoise"]
1207       when 2
1208         commandString << " --denoise=\\\"weak\\\""
1209       when 3
1210         commandString << " --denoise=\\\"medium\\\""
1211       when 4
1212         commandString << " --denoise=\\\"strong\\\""
1213       end
1214       
1215       if hash["PictureDetelecine"] == 2 then commandString << " --detelecine" end
1216       if hash["PictureDeblock"] != 0 then commandString << " --deblock=" << hash["PictureDeblock"].to_s end
1217       if hash["PictureDecomb"] == 2 then commandString << " --decomb" end
1218     end
1219     
1220     #Anamorphic
1221     if hash["PicturePAR"] == 1
1222       commandString << " --strict-anamorphic"
1223     elsif hash["PicturePAR"] == 2
1224       commandString << " --loose-anamorphic"
1225     elsif hash["PicturePAR"] == 3
1226       commandString << " --custom-anamorphic"
1227     end
1228     
1229     #Booleans
1230     if hash["ChapterMarkers"] == 1 then commandString << " -m" end
1231     if hash["VideoGrayScale"] == 1 then commandString << " -g" end
1232     if hash["VideoTwoPass"] == 1 then commandString << " -2" end
1233     if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end
1234     
1235       #x264 Options
1236       if hash["x264Option"] != ""
1237         commandString << " -x "
1238         commandString << hash["x264Option"]
1239       end
1240     
1241     commandString << "\\n\");"
1242     
1243     # That's it, print to screen now
1244     puts commandString
1245     puts  "\n"
1246   end
1247   
1248 end
1249
1250 # First grab the specified CLI options
1251 options = readOptions
1252
1253 # Only run if one of the useful CLI flags have been passed
1254 if options.cliraw == true || options.cliparse == true || options.api == true || options.apilist == true
1255   # This line is the ignition -- generates hashes of
1256   # presets and then displays them to the screen
1257   # with the options the user selects on the CLI. 
1258   Display.new( Presets.new.hashMasterList, options )
1259 else
1260   # Direct the user to the help
1261   puts "\n\tUsage: manicure.rb [options]"
1262   puts "\tSee help with -h or --help"
1263 end