OSDN Git Service

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