OSDN Git Service

merge 0.9.4 to jp
[handbrake-jp/handbrake-jp.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 /AVI/
279       commandString << "avi "
280     when /OGM/
281       commandString << "ogm "
282     when /MKV/
283       commandString << "mkv "
284     end
285     
286     #Video encoder
287     if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
288       commandString << " -e "
289       case hash["VideoEncoder"]
290       when /x264/
291         commandString << "x264"
292       when /XviD/
293         commandString << "xvid"
294       end
295     end
296
297     #VideoRateControl
298     case hash["VideoQualityType"]
299     when 0
300       commandString << " -S " << hash["VideoTargetSize"]
301     when 1
302       commandString << " -b " << hash["VideoAvgBitrate"]
303     when 2
304       commandString << " -q " << hash["VideoQualitySlider"].to_s
305     end
306
307     #FPS
308     if hash["VideoFramerate"] != "Same as source"
309       if hash["VideoFramerate"] == "23.976 (NTSC Film)"
310         commandString << " -r " << "23.976"
311       elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
312         commandString << " -r " << "29.97"
313       elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
314         commandString << " -r " << "25"
315       else
316         commandString << " -r " << hash["VideoFramerate"]
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 /AVI/
395       commandString << "avi"
396     when /OGM/
397       commandString << "ogm"
398     when /MKV/
399       commandString << "mkv"
400     end
401     
402     #iPod MP4 atom
403     if hash["Mp4iPodCompatible"].to_i == 1
404       commandString << " -I"
405     end
406     
407     # 64-bit files
408     if hash["Mp4LargeFile"] == 1
409       commandString << " -4"
410     end
411     
412     #Cropping
413     if hash["PictureAutoCrop"] == 0
414       commandString << " --crop "
415       commandString << hash["PictureTopCrop"].to_s
416       commandString << ":"
417       commandString << hash["PictureBottomCrop"].to_s
418       commandString << ":"
419       commandString << hash["PictureLeftCrop"].to_s
420       commandString << ":"
421       commandString << hash["PictureRightCrop"].to_s
422     end
423     
424     #Dimensions
425     if hash["PictureWidth"] != 0
426       commandString << " -X "
427       commandString << hash["PictureWidth"].to_s
428     end
429     if hash["PictureHeight"] != 0
430       commandString << " -Y "
431       commandString << hash["PictureHeight"].to_s
432     end
433     
434     #Subtitles
435     if hash["Subtitles"] != "None"
436       if hash["Subtitles"] == "Autoselect"
437         commandString << " --subtitle-scan"
438       else
439         commandString << " -s "
440         commandString << hash["Subtitles"]
441       end
442     end
443
444     #Video Filters
445     if hash["UsesPictureFilters"] == 1
446       
447       case hash["PictureDeinterlace"]
448       when 1
449         commandString << " --deinterlace=\"fast\""
450       when 2
451         commandString << " --deinterlace=\slow\""
452       when 3
453         commandString << " --deinterlace=\"slower\""
454       when 4
455         commandString << " --deinterlace=\"slowest\""
456       end
457       
458       case hash["PictureDenoise"]
459       when 1
460         commandString << " --denoise=\"weak\""
461       when 2
462         commandString << " --denoise=\"medium\""
463       when 3
464         commandString << " --denoise=\"strong\""
465       end
466       
467       if hash["PictureDetelecine"] == 1 then commandString << " --detelecine" end
468       if hash["PictureDeblock"] == 1 then commandString << " --deblock" end
469       if hash["VFR"].to_i == 1 then commandString << " --vfr" end
470       if hash["PictureDecomb"] == 1 then commandString << " --decomb" end
471       
472     end
473     
474     #Anamorphic
475     if hash["PicturePAR"] == 1
476       commandString << " --strict-anamorphic"
477     elsif hash["PicturePAR"] == 2
478       commandString << " --loose-anamorphic"
479     end
480
481     #Booleans
482     if hash["ChapterMarkers"] == 1 then commandString << " -m" end
483     if hash["VideoGrayScale"] == 1 then commandString << " -g" end
484     if hash["VideoTwoPass"] == 1 then commandString << " -2" end
485     if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end
486
487     #x264 Options
488     if hash["x264Option"] != ""
489       commandString << " -x "
490       commandString << hash["x264Option"]
491     end
492     
493     # That's it, print to screen now
494     puts commandString
495     
496     #puts "*" * @columnWidth
497
498     puts  "\n"
499   end
500   
501   def generateCLIFolderParse( hash, depth ) # Shows the folder for wrappers to parse
502     commandString = ""
503     depth.times do
504       commandString << "   "
505     end
506     (depth+1).times do
507       commandString << "<"
508     end
509     commandString << " " << hash["PresetName"] << "\n\n"
510     puts commandString
511   end
512   
513   def generateCLIFolderCloserParse( depth )
514     commandString = ""
515     depth.times do
516       commandString << "   "
517     end
518     (depth+1).times do
519       commandString << ">"
520     end
521     commandString << "\n\n"
522     puts commandString
523   end
524   
525   def generateCLIParse(hash, depth) # Makes a CLI equivalent of all user presets, for wrappers to parse
526     commandString = ""
527     depth.times do
528       commandString << "   "
529     end
530     commandString << '+ ' << hash["PresetName"] << ":"
531         
532     #Video encoder
533     if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
534       commandString << " -e "
535       case hash["VideoEncoder"]
536       when /x264/
537         commandString << "x264"
538       when /XviD/
539         commandString << "xvid"
540       end
541     end
542
543     #VideoRateControl
544     case hash["VideoQualityType"]
545     when 0
546       commandString << " -S " << hash["VideoTargetSize"]
547     when 1
548       commandString << " -b " << hash["VideoAvgBitrate"]
549     when 2
550       commandString << " -q " << hash["VideoQualitySlider"].to_s
551     end
552
553     #FPS
554     if hash["VideoFramerate"] != "Same as source"
555       if hash["VideoFramerate"] == "23.976 (NTSC Film)"
556         commandString << " -r " << "23.976"
557       elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
558         commandString << " -r " << "29.97"
559       elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
560         commandString << " -r " << "25"
561       else
562         commandString << " -r " << hash["VideoFramerate"]
563       end
564     end
565     
566     #Audio tracks
567     audioBitrates = ""
568     audioEncoders = ""
569     audioMixdowns = ""
570     audioSamplerates = ""
571     audioTracks = ""
572     audioTrackDRCs = ""
573     audioCount = hash["AudioList"].size
574     
575     hash["AudioList"].each do |audioTrack|
576       audioCount = audioCount - 1
577
578       #Bitrates
579       audioBitrates << audioTrack["AudioBitrate"]
580       
581       #Encoders
582       case audioTrack["AudioEncoder"]
583         when /AC3 /
584           audioEncoders << "ac3"
585         when /AAC/
586           audioEncoders << "faac"
587         when /Vorbis/
588           audioEncoders << "vorbis"
589         when /MP3/
590           audioEncoders << "lame"
591       end
592       
593       #Mixdowns
594       case audioTrack["AudioMixdown"]
595       when /Mono/
596         audioMixdowns << "mono"
597       when /Stereo/
598         audioMixdowns << "stereo"
599       when /Dolby Surround/
600         audioMixdowns << "dpl1"
601       when /Dolby Pro Logic II/
602         audioMixdowns << "dpl2"
603       when /discrete/
604         audioMixdowns << "6ch"
605       when /Passthru/
606         audioMixdowns << "auto"
607       end
608       
609       #Samplerates
610       audioSamplerates << audioTrack["AudioSamplerate"]
611       
612       #Tracks
613       audioTracks << audioTrack["AudioTrack"].to_s
614       
615       #DRC
616       audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
617       
618       if audioCount > 0
619         audioBitrates << ","
620         audioEncoders << ","
621         audioMixdowns << ","
622         audioSamplerates << ","
623         audioTracks << ","
624         audioTrackDRCs << ","
625       end
626       
627     end
628     commandString << " -a " << audioTracks
629     commandString << " -E " << audioEncoders
630     commandString << " -B " << audioBitrates
631     commandString << " -6 " << audioMixdowns
632     commandString << " -R " << audioSamplerates
633     commandString << " -D " << audioTrackDRCs
634     
635     #Container
636     commandString << " -f "
637     case hash["FileFormat"]
638     when /MP4/
639       commandString << "mp4"
640     when /AVI/
641       commandString << "avi"
642     when /OGM/
643       commandString << "ogm"
644     when /MKV/
645       commandString << "mkv"
646     end
647     
648     #iPod MP4 atom
649     if hash["Mp4iPodCompatible"].to_i == 1
650       commandString << " -I"
651     end
652     
653     # 64-bit files
654     if hash["Mp4LargeFile"] == 1
655       commandString << " -4"
656     end
657     
658     #Cropping
659     if hash["PictureAutoCrop"] == 0
660       commandString << " --crop "
661       commandString << hash["PictureTopCrop"].to_s
662       commandString << ":"
663       commandString << hash["PictureBottomCrop"].to_s
664       commandString << ":"
665       commandString << hash["PictureLeftCrop"].to_s
666       commandString << ":"
667       commandString << hash["PictureRightCrop"].to_s
668     end
669     
670     #Dimensions
671     if hash["PictureWidth"] != 0
672       commandString << " -X "
673       commandString << hash["PictureWidth"].to_s
674     end
675     if hash["PictureHeight"] != 0
676       commandString << " -Y "
677       commandString << hash["PictureHeight"].to_s
678     end
679     
680     #Subtitles
681     if hash["Subtitles"] != "None"
682       if hash["Subtitles"] == "Autoselect"
683         commandString << " --subtitle-scan"
684       else
685         commandString << " -s "
686         commandString << hash["Subtitles"]
687       end
688     end
689     
690     #Video Filters
691     if hash["UsesPictureFilters"] == 1
692       
693       case hash["PictureDeinterlace"]
694       when 1
695         commandString << " --deinterlace=\"fast\""
696       when 2
697         commandString << " --deinterlace=\slow\""
698       when 3
699         commandString << " --deinterlace=\"slower\""
700       when 4
701         commandString << " --deinterlace=\"slowest\""
702       end
703       
704       case hash["PictureDenoise"]
705       when 1
706         commandString << " --denoise=\"weak\""
707       when 2
708         commandString << " --denoise=\"medium\""
709       when 3
710         commandString << " --denoise=\"strong\""
711       end
712       
713       if hash["PictureDetelecine"] == 1 then commandString << " --detelecine" end
714       if hash["PictureDeblock"] == 1 then commandString << " --deblock" end
715       if hash["VFR"].to_i == 1 then commandString << " --vfr" end
716       if hash["PictureDecomb"] == 1 then commandString << " --decomb" end
717     end
718
719     #Anamorphic
720     if hash["PicturePAR"] == 1
721       commandString << " --strict-anamorphic"
722     elsif hash["PicturePAR"] == 2
723       commandString << " --loose-anamorphic"
724     end
725     
726     #Booleans
727     if hash["ChapterMarkers"] == 1 then commandString << " -m" end
728     if hash["VideoGrayScale"] == 1 then commandString << " -g" end
729     if hash["VideoTwoPass"] == 1 then commandString << " -2" end
730     if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end
731
732     #x264 Options
733     if hash["x264Option"] != ""
734       commandString << " -x "
735       commandString << hash["x264Option"]
736     end
737     
738     # That's it, print to screen now
739     puts commandString
740     
741     #puts "*" * @columnWidth
742
743     puts  "\n"
744   end
745
746   def generateAPIcalls(hash) # Makes a C version of the preset ready for coding into the CLI
747     
748     commandString = "if (!strcmp(preset_name, \"" << hash["PresetName"] << "\"))\n{\n    "
749     
750     #Filename suffix
751     commandString << "if( !mux )\n    "
752     commandString << "{\n    "
753
754     case hash["FileFormat"]
755     when /MP4/
756       commandString << "    mux = " << "HB_MUX_MP4;\n    "
757     when /AVI/
758       commandString << "    mux = " << "HB_MUX_AVI;\n    "
759     when /OGM/
760       commandString << "    mux = " << "HB_MUX_OGM;\n    "
761     when /MKV/
762       commandString << "    mux = " << "HB_MUX_MKV;\n    "
763     end
764     commandString << "}\n    "
765     
766     #iPod MP4 atom
767     if hash["Mp4iPodCompatible"].to_i == 1
768       commandString << "job->ipod_atom = 1;\n   "
769     end
770     
771     # 64-bit files
772     if hash["Mp4LargeFile"] == 1
773       commandString << "job->largeFileSize = 1;\n    "
774     end
775     
776     #Video encoder
777     if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
778       commandString << "vcodec = "
779       case hash["VideoEncoder"]
780       when /x264/
781         commandString << "HB_VCODEC_X264;\n    "
782       when /XviD/
783         commandString << "HB_VCODEC_XVID;\n    "        
784       end
785     end
786
787     #VideoRateControl
788     case hash["VideoQualityType"]
789     when 0
790       commandString << "size = " << hash["VideoTargetSize"] << ";\n    "
791     when 1
792       commandString << "job->vbitrate = " << hash["VideoAvgBitrate"] << ";\n    "
793     when 2
794       commandString << "job->vquality = " << hash["VideoQualitySlider"].to_s << ";\n    "
795       commandString << "job->crf = 1;\n    "
796     end
797
798     #FPS
799     if hash["VideoFramerate"] != "Same as source"
800       if hash["VideoFramerate"] == "23.976 (NTSC Film)"
801         commandString << "job->vrate_base = " << "1126125;\n    "
802       elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
803         commandString << "job->vrate_base = " << "900900;\n    "
804       elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
805         commandString << "job->vrate_base = " << "1080000\n    "
806       # Gotta add the rest of the framerates for completion's sake.
807       end
808       commandString << "job->cfr = 1;\n    "
809     end
810     
811     #Audio tracks
812     audioBitrates = ""
813     audioEncoders = ""
814     audioMixdowns = ""
815     audioSamplerates = ""
816     audioTracks = ""
817     audioTrackDRCs = ""
818     audioCount = hash["AudioList"].size
819
820     hash["AudioList"].each do |audioTrack|
821       audioCount = audioCount - 1
822
823       #Bitrates
824       audioBitrates << audioTrack["AudioBitrate"]
825
826       #Encoders
827       case audioTrack["AudioEncoder"]
828         when /AC3 /
829           audioEncoders << "ac3"
830         when /AAC/
831           audioEncoders << "faac"
832         when /Vorbis/
833           audioEncoders << "vorbis"
834         when /MP3/
835           audioEncoders << "lame"
836       end
837
838       #Mixdowns
839       case audioTrack["AudioMixdown"]
840       when /Mono/
841         audioMixdowns << "mono"
842       when /Stereo/
843         audioMixdowns << "stereo"
844       when /Dolby Surround/
845         audioMixdowns << "dpl1"
846       when /Dolby Pro Logic II/
847         audioMixdowns << "dpl2"
848       when /discrete/
849         audioMixdowns << "6ch"
850       when /Passthru/
851         audioMixdowns << "auto"
852       end
853
854       #Samplerates
855       audioSamplerates << audioTrack["AudioSamplerate"]
856
857       #Tracks
858       audioTracks << audioTrack["AudioTrack"].to_s
859
860       #DRC
861       audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
862
863       if audioCount > 0
864         audioBitrates << ","
865         audioEncoders << ","
866         audioMixdowns << ","
867         audioSamplerates << ","
868         audioTracks << ","
869         audioTrackDRCs << ","
870       end
871
872     end
873     commandString << "if( !atracks )\n    "
874     commandString << "{\n    "
875     commandString << "    atracks = strdup(\"" << audioTracks
876     commandString << "\");\n    "
877     commandString << "}\n    "
878
879     commandString << "if( !acodecs )\n    "
880     commandString << "{\n    "
881     commandString << "    acodecs = strdup(\"" << audioEncoders
882     commandString << "\");\n    "
883     commandString << "}\n    "
884
885     commandString << "if( !abitrates )\n    "
886     commandString << "{\n    "
887     commandString << "    abitrates = strdup(\"" << audioBitrates
888     commandString << "\");\n    "
889     commandString << "}\n    "
890
891     commandString << "if( !mixdowns )\n    "
892     commandString << "{\n    "
893     commandString << "    mixdowns = strdup(\"" << audioMixdowns
894     commandString << "\");\n    "
895     commandString << "}\n    "
896
897     commandString << "if( !arates )\n    "
898     commandString << "{\n    "
899     commandString << "    arates = strdup(\"" << audioSamplerates
900     commandString << "\");\n    "
901     commandString << "}\n    "
902
903     commandString << "if( !dynamic_range_compression )\n    "
904     commandString << "{\n    "
905     commandString << "    dynamic_range_compression = strdup(\"" << audioTrackDRCs
906     commandString << "\");\n    "
907     commandString << "}\n    "
908     
909     #Cropping
910     if hash["PictureAutoCrop"] == 0
911       commandString << "job->crop[0] = " << hash["PictureTopCrop"].to_s << ";\n    "
912       commandString << "job->crop[1] = " << hash["PictureBottomCrop"].to_s << ";\n    "
913       commandString << "job->crop[2] = " << hash["PictureLeftCrop"].to_s << ";\n    "
914       commandString << "job->crop[4] - " << hash["PictureRightCrop"].to_s << ";\n    "
915     end
916     
917     #Dimensions
918     if hash["PictureWidth"] != 0
919       commandString << "maxWidth = "
920       commandString << hash["PictureWidth"].to_s << ";\n    "
921     end
922     if hash["PictureHeight"] != 0
923       commandString << "maxHeight = "
924       commandString << hash["PictureHeight"].to_s << ";\n    "
925     end
926     
927     #Subtitles
928     if hash["Subtitles"] != "None"
929       if hash["Subtitles"] == "Autoselect"
930         commandString << "subtitle_scan = 1;\n    "
931       else
932         commandString << "job->subtitle = "
933         commandString << ( hash["Subtitles"].to_i - 1).to_s << ";\n    "
934       end
935     end
936     
937     #x264 Options
938     if hash["x264Option"] != ""
939       commandString << "if( !x264opts )\n    "
940       commandString << "{\n    "
941       commandString << "    x264opts = strdup(\""
942       commandString << hash["x264Option"] << "\");\n    "
943       commandString << "}\n    "
944     end
945     
946     #Video Filters
947     if hash["UsesPictureFilters"] == 1
948       
949       case hash["PictureDeinterlace"]
950       when 1
951         commandString << "deinterlace = 1;\n    "
952         commandString << "deinterlace_opt = \"-1\";\n    "
953       when 2
954         commandString << "deinterlace = 1;\n    "
955         commandString << "deinterlace_opt = \"2\";\n    "
956       when 3
957         commandString << "deinterlace = 1;\n    "
958         commandString << "deinterlace_opt = \"0\";\n    "
959       when 4
960         commandString << "deinterlace = 1;\n    "
961         commandString << "deinterlace_opt = \"1:-1:1\";\n    "
962       end
963       
964       case hash["PictureDenoise"]
965       when 1
966         commandString << "denoise = 1;\n    "
967         commandString << "denoise_opt = \"2:1:2:3\";\n    "
968       when 2
969         commandString << "denoise = 1;\n    "
970         commandString << "denoise_opt = \"3:2:2:3\";\n    "
971       when 3
972         commandString << "denoise = 1;\n    "
973         commandString << "denoise_opt = \"7:7:5:5\";\n    "
974       end
975       
976       if hash["PictureDetelecine"] == 1 then commandString << "detelecine = 1;\n    " end
977       if hash["PictureDeblock"] == 1 then commandString << "deblock = 1;\n    " end
978       if hash["VFR"].to_i == 1 then commandString << "vfr = 1;\n    " end
979       if hash["PictureDecomb"] == 1 then commandString << "decomb = 1;\n    " end
980       
981     end
982     
983     #Anamorphic
984     if hash["PicturePAR"] == 1
985       commandString << "anamorphic_mode = 1;\n    "
986     elsif hash["PicturePAR"] == 2
987       commandString << "anamorphic_mode = 2;\n    "
988     end
989     
990     #Booleans
991     if hash["ChapterMarkers"] == 1 then commandString << "job->chapter_markers = 1;\n    " end
992     if hash["VideoGrayScale"] == 1 then commandString << "job->grayscale = 1;\n    " end
993     if hash["VideoTwoPass"] == 1 then commandString << "twoPass = 1;\n    " end
994     if hash["VideoTurboTwoPass"] == 1 then commandString << "turbo_opts_enabled = 1;\n" end
995     
996     commandString << "}"
997     
998     # That's it, print to screen now
999     puts commandString
1000     #puts "*" * @columnWidth
1001     puts  "\n"
1002   end
1003   
1004   def generateAPIFolderList( hash, depth )
1005     commandString = ""
1006     
1007     commandString << "    printf(\"\\n"
1008     depth.times do
1009       commandString << "   "
1010     end
1011     (depth+1).times do
1012       commandString << "<"
1013     end
1014     commandString << " " << hash["PresetName"]
1015     commandString << "\\n\");\n\n"    
1016     puts commandString
1017   end
1018   
1019   def generateAPIFolderCloserList( depth )
1020     commandString = ""
1021     
1022     commandString << "    printf(\"\\n"
1023     depth.times do
1024       commandString << "   "
1025     end
1026     (depth+1).times do
1027       commandString << ">"
1028     end
1029     commandString << "\\n\");\n\n"    
1030     puts commandString
1031   end
1032   
1033   def generateAPIList(hash, depth) # Makes a list of the CLI options a built-in CLI preset uses, for wrappers to parse
1034     commandString = ""
1035     commandString << "    printf(\"\\n"
1036     depth.times do
1037       commandString << "   "
1038     end
1039            
1040     commandString << "+ " << hash["PresetName"] << ": "
1041         
1042     #Video encoder
1043     if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
1044       commandString << " -e "
1045       case hash["VideoEncoder"]
1046       when /x264/
1047         commandString << "x264 "
1048       when /XviD/
1049         commandString << "xvid "
1050       end
1051     end
1052
1053     #VideoRateControl
1054     case hash["VideoQualityType"]
1055     when 0
1056       commandString << " -S " << hash["VideoTargetSize"]
1057     when 1
1058       commandString << " -b " << hash["VideoAvgBitrate"]
1059     when 2
1060       commandString << " -q " << hash["VideoQualitySlider"].to_s
1061     end
1062
1063     #FPS
1064     if hash["VideoFramerate"] != "Same as source"
1065       if hash["VideoFramerate"] == "23.976 (NTSC Film)"
1066         commandString << " -r " << "23.976"
1067       elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
1068         commandString << " -r " << "29.97"
1069       elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
1070         commandString << " -r " << "25"
1071       else
1072         commandString << " -r " << hash["VideoFramerate"]
1073       end
1074     end
1075     
1076     #Audio tracks
1077     audioBitrates = ""
1078     audioEncoders = ""
1079     audioMixdowns = ""
1080     audioSamplerates = ""
1081     audioTracks = ""
1082     audioTrackDRCs = ""
1083     audioCount = hash["AudioList"].size
1084     
1085     hash["AudioList"].each do |audioTrack|
1086       audioCount = audioCount - 1
1087
1088       #Bitrates
1089       audioBitrates << audioTrack["AudioBitrate"]
1090       
1091       #Encoders
1092       case audioTrack["AudioEncoder"]
1093         when /AC3 /
1094           audioEncoders << "ac3"
1095         when /AAC/
1096           audioEncoders << "faac"
1097         when /Vorbis/
1098           audioEncoders << "vorbis"
1099         when /MP3/
1100           audioEncoders << "lame"
1101       end
1102       
1103       #Mixdowns
1104       case audioTrack["AudioMixdown"]
1105       when /Mono/
1106         audioMixdowns << "mono"
1107       when /Stereo/
1108         audioMixdowns << "stereo"
1109       when /Dolby Surround/
1110         audioMixdowns << "dpl1"
1111       when /Dolby Pro Logic II/
1112         audioMixdowns << "dpl2"
1113       when /discrete/
1114         audioMixdowns << "6ch"
1115       when /Passthru/
1116         audioMixdowns << "auto"
1117       end
1118       
1119       #Samplerates
1120       audioSamplerates << audioTrack["AudioSamplerate"]
1121       
1122       #Tracks
1123       audioTracks << audioTrack["AudioTrack"].to_s
1124       
1125       #DRC
1126       audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
1127       
1128       if audioCount > 0
1129         audioBitrates << ","
1130         audioEncoders << ","
1131         audioMixdowns << ","
1132         audioSamplerates << ","
1133         audioTracks << ","
1134         audioTrackDRCs << ","
1135       end
1136       
1137     end
1138     commandString << " -a " << audioTracks
1139     commandString << " -E " << audioEncoders
1140     commandString << " -B " << audioBitrates
1141     commandString << " -6 " << audioMixdowns
1142     commandString << " -R " << audioSamplerates
1143     commandString << " -D " << audioTrackDRCs
1144     
1145     #Container
1146     commandString << " -f "
1147     case hash["FileFormat"]
1148     when /MP4/
1149       commandString << "mp4"
1150     when /AVI/
1151       commandString << "avi"
1152     when /OGM/
1153       commandString << "ogm"
1154     when /MKV/
1155       commandString << "mkv"
1156     end
1157     
1158     #iPod MP4 atom
1159     if hash["Mp4iPodCompatible"].to_i == 1
1160       commandString << " -I"
1161     end
1162     
1163     # 64-bit files
1164     if hash["Mp4LargeFile"] == 1
1165       commandString << " -4"
1166     end
1167     
1168     #Cropping
1169     if hash["PictureAutoCrop"] == 0
1170       commandString << " --crop "
1171       commandString << hash["PictureTopCrop"].to_s
1172       commandString << ":"
1173       commandString << hash["PictureBottomCrop"].to_s
1174       commandString << ":"
1175       commandString << hash["PictureLeftCrop"].to_s
1176       commandString << ":"
1177       commandString << hash["PictureRightCrop"].to_s
1178     end
1179     
1180     #Dimensions
1181     if hash["PictureWidth"] != 0
1182       commandString << " -X "
1183       commandString << hash["PictureWidth"].to_s
1184     end
1185     if hash["PictureHeight"] != 0
1186       commandString << " -Y "
1187       commandString << hash["PictureHeight"].to_s
1188     end
1189     
1190     #Subtitles
1191     if hash["Subtitles"] != "None"
1192       if hash["Subtitles"] == "Autoselect"
1193         commandString << " --subtitle-scan"
1194       else
1195         commandString << " -s "
1196         commandString << hash["Subtitles"]
1197       end
1198     end
1199     
1200     #Video Filters
1201     if hash["UsesPictureFilters"] == 1
1202       
1203       case hash["PictureDeinterlace"]
1204       when 1
1205         commandString << " --deinterlace=\\\"fast\\\""
1206       when 2
1207         commandString << " --deinterlace=\\\slow\\\""
1208       when 3
1209         commandString << " --deinterlace=\\\"slower\\\""
1210       when 4
1211         commandString << " --deinterlace=\\\"slowest\\\""
1212       end
1213       
1214       case hash["PictureDenoise"]
1215       when 1
1216         commandString << " --denoise=\\\"weak\\\""
1217       when 2
1218         commandString << " --denoise=\\\"medium\\\""
1219       when 3
1220         commandString << " --denoise=\\\"strong\\\""
1221       end
1222       
1223       if hash["PictureDetelecine"] == 1 then commandString << " --detelecine" end
1224       if hash["PictureDeblock"] == 1 then commandString << " --deblock" end
1225       if hash["VFR"].to_i == 1 then commandString << " --vfr" end
1226       if hash["PictureDecomb"] == 1 then commandString << " --decomb" end
1227     end
1228     
1229     #Anamorphic
1230     if hash["PicturePAR"] == 1
1231       commandString << " --strict-anamorphic"
1232     elsif hash["PicturePAR"] == 2
1233       commandString << " --loose-anamorphic"
1234     end
1235     
1236     #Booleans
1237     if hash["ChapterMarkers"] == 1 then commandString << " -m" end
1238     if hash["VideoGrayScale"] == 1 then commandString << " -g" end
1239     if hash["VideoTwoPass"] == 1 then commandString << " -2" end
1240     if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end
1241     
1242       #x264 Options
1243       if hash["x264Option"] != ""
1244         commandString << " -x "
1245         commandString << hash["x264Option"]
1246       end
1247     
1248     commandString << "\\n\");"
1249     
1250     # That's it, print to screen now
1251     puts commandString
1252     puts  "\n"
1253   end
1254   
1255 end
1256
1257 # First grab the specified CLI options
1258 options = readOptions
1259
1260 # Only run if one of the useful CLI flags have been passed
1261 if options.cliraw == true || options.cliparse == true || options.api == true || options.apilist == true
1262   # This line is the ignition -- generates hashes of
1263   # presets and then displays them to the screen
1264   # with the options the user selects on the CLI. 
1265   Display.new( Presets.new.hashMasterList, options )
1266 else
1267   # Direct the user to the help
1268   puts "\n\tUsage: manicure.rb [options]"
1269   puts "\tSee help with -h or --help"
1270 end