OSDN Git Service

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