3 This file is part of the HandBrake source code.
\r
4 Homepage: <http://handbrake.fr>.
\r
5 It may be used under the terms of the GNU General Public License. */
\r
8 using System.Globalization;
\r
9 using System.Text.RegularExpressions;
\r
10 using System.Windows.Forms;
\r
11 using System.Collections;
\r
13 namespace Handbrake.Functions
\r
15 internal class QueryParser
\r
17 private static readonly CultureInfo Culture = new CultureInfo("en-US", false);
\r
22 public int DVDTitle { get; set; }
\r
23 public int DVDChapterStart { get; set; }
\r
24 public int DVDChapterFinish { get; set; }
\r
27 public string Format { get; set; }
\r
28 public Boolean LargeMP4 { get; set; }
\r
29 public Boolean IpodAtom { get; set; }
\r
30 public Boolean OptimizeMP4 { get; set; }
\r
33 public int Width { get; set; }
\r
34 public int Height { get; set; }
\r
35 public int MaxWidth { get; set; }
\r
36 public int MaxHeight { get; set; }
\r
37 public string CropValues { get; set; }
\r
38 public string CropTop { get; set; }
\r
39 public string CropBottom { get; set; }
\r
40 public string CropLeft { get; set; }
\r
41 public string CropRight { get; set; }
\r
42 public int AnamorphicMode { get; set; }
\r
43 public Boolean keepDisplayAsect { get; set; }
\r
44 public double displayWidthValue { get; set; }
\r
45 public int pixelAspectWidth { get; set; }
\r
46 public int pixelAspectHeight { get; set; }
\r
47 public int AnamorphicModulus { get; set; }
\r
50 public string DeTelecine { get; set; }
\r
51 public int DeBlock { get; set; }
\r
52 public string DeInterlace { get; set; }
\r
53 public string DeNoise { get; set; }
\r
54 public string Decomb { get; set; }
\r
57 public string VideoEncoder { get; set; }
\r
58 public Boolean Grayscale { get; set; }
\r
59 public Boolean TwoPass { get; set; }
\r
60 public Boolean TurboFirstPass { get; set; }
\r
61 public string VideoFramerate { get; set; }
\r
62 public string AverageVideoBitrate { get; set; }
\r
63 public string VideoTargetSize { get; set; }
\r
64 public float VideoQuality { get; set; }
\r
67 public ArrayList AudioInformation { get; set; }
\r
68 public string Subtitles { get; set; }
\r
69 public Boolean ForcedSubtitles { get; set; }
\r
72 public Boolean ChapterMarkers { get; set; }
\r
75 public string H264Query { get; set; }
\r
76 public Boolean Verbose { get; set; }
\r
78 // Preset Information
\r
79 public int PresetBuildNumber { get; set; }
\r
80 public string PresetDescription { get; set; }
\r
81 public string PresetName { get; set; }
\r
82 public string Type { get; set; }
\r
83 public Boolean UsesMaxPictureSettings { get; set; }
\r
84 public Boolean UsesPictureFilters { get; set; }
\r
85 public Boolean UsesPictureSettings { get; set; }
\r
90 /// Takes in a query which can be in any order and parses it.
\r
91 /// All varibles are then set so they can be used elsewhere.
\r
93 /// <param name="input">A ClI Query</param>
\r
94 /// <returns>A Parsed Query</returns>
\r
95 public static QueryParser Parse(String input)
\r
97 var thisQuery = new QueryParser();
\r
99 #region Regular Expressions
\r
102 Match title = Regex.Match(input, @"-t ([0-9]*)");
\r
103 Match chapters = Regex.Match(input, @"-c ([0-9-]*)");
\r
106 Match format = Regex.Match(input, @"-f ([a-z0-9a-z0-9a-z0-9]*)");
\r
107 Match grayscale = Regex.Match(input, @" -g");
\r
108 Match largerMp4 = Regex.Match(input, @" -4");
\r
109 Match ipodAtom = Regex.Match(input, @" -I");
\r
111 //Picture Settings Tab
\r
112 Match width = Regex.Match(input, @"-w ([0-9]*)");
\r
113 Match height = Regex.Match(input, @"-l ([0-9]*)");
\r
114 Match maxWidth = Regex.Match(input, @"-X ([0-9]*)");
\r
115 Match maxHeight = Regex.Match(input, @"-Y ([0-9]*)");
\r
116 Match crop = Regex.Match(input, @"--crop ([0-9]*):([0-9]*):([0-9]*):([0-9]*)");
\r
118 Match looseAnamorphic = Regex.Match(input, @"--loose-anamorphic");
\r
119 Match strictAnamorphic = Regex.Match(input, @"--strict-anamorphic");
\r
120 Match customAnamorphic = Regex.Match(input, @"--custom-anamorphic");
\r
122 Match keepDisplayAsect = Regex.Match(input, @"--keep-display-aspect");
\r
123 Match displayWidth = Regex.Match(input, @"--display-width ([0-9*])");
\r
124 Match pixelAspect = Regex.Match(input, @"--pixel-aspect ([0-9]*):([0-9]*)");
\r
125 Match modulus = Regex.Match(input, @"--modulus ([0-9*])");
\r
127 // Picture Settings - Filters
\r
128 Match decomb = Regex.Match(input, @" --decomb");
\r
129 Match decombValue = Regex.Match(input, @" --decomb=\""([a-zA-Z0-9.:]*)\""");
\r
130 Match deinterlace = Regex.Match(input, @"--deinterlace=\""([a-zA-Z0-9.:]*)\""");
\r
131 Match denoise = Regex.Match(input, @"--denoise=\""([a-zA-Z0-9.:]*)\""");
\r
132 Match deblock = Regex.Match(input, @"--deblock=([0-9:]*)");
\r
133 Match detelecine = Regex.Match(input, @"--detelecine");
\r
134 Match detelecineValue = Regex.Match(input, @" --detelecine=\""([a-zA-Z0-9.:]*)\""");
\r
136 //Video Settings Tab
\r
137 Match videoEncoder = Regex.Match(input, @"-e ([a-zA-Z0-9]*)");
\r
138 Match videoFramerate = Regex.Match(input, @"-r ([0-9.]*)");
\r
139 Match videoBitrate = Regex.Match(input, @"-b ([0-9]*)");
\r
140 Match videoQuality = Regex.Match(input, @"-q ([0-9.]*)");
\r
141 Match videoFilesize = Regex.Match(input, @"-S ([0-9.]*)");
\r
142 Match twoPass = Regex.Match(input, @" -2");
\r
143 Match turboFirstPass = Regex.Match(input, @" -T");
\r
144 Match optimizeMP4 = Regex.Match(input, @" -O");
\r
146 //Audio Settings Tab
\r
147 Match noAudio = Regex.Match(input, @"-a none");
\r
148 Match audioTracks = Regex.Match(input, @"-a ([0-9,]*)");
\r
149 Match audioTrackMixes = Regex.Match(input, @"-6 ([0-9a-zA-Z,]*)");
\r
150 Match audioEncoders = Regex.Match(input, @"-E ([a-zA-Z0-9+,]*)");
\r
151 Match audioBitrates = Regex.Match(input, @"-B ([0-9a-zA-Z,]*)"); // Auto = a-z
\r
152 Match audioSampleRates = Regex.Match(input, @"-R ([0-9a-zA-Z.,]*)"); // Auto = a-z
\r
153 Match drcValues = Regex.Match(input, @"-D ([0-9.,]*)");
\r
155 Match subtitles = Regex.Match(input, @"-s ([0-9a-zA-Z]*)");
\r
156 Match subScan = Regex.Match(input, @" -U");
\r
157 Match forcedSubtitles = Regex.Match(input, @" -F");
\r
160 Match chapterMarkers = Regex.Match(input, @" -m");
\r
161 Match chapterMarkersFileMode = Regex.Match(input, @"--markers");
\r
164 Match x264 = Regex.Match(input, @"-x ([.,/a-zA-Z0-9=:-]*)");
\r
167 Match verbose = Regex.Match(input, @" -v");
\r
171 #region Set Varibles
\r
178 thisQuery.DVDTitle = int.Parse(title.ToString().Replace("-t ", ""));
\r
180 if (chapters.Success)
\r
182 string[] actTitles = chapters.ToString().Replace("-c ", "").Split('-');
\r
183 thisQuery.DVDChapterStart = int.Parse(actTitles[0]);
\r
184 if (actTitles.Length > 1)
\r
186 thisQuery.DVDChapterFinish = int.Parse(actTitles[1]);
\r
189 if ((thisQuery.DVDChapterStart == 1) && (thisQuery.DVDChapterFinish == 0))
\r
190 thisQuery.DVDChapterFinish = thisQuery.DVDChapterStart;
\r
194 #region Output Settings
\r
196 if (format.Success)
\r
197 thisQuery.Format = format.ToString().Replace("-f ", "");
\r
198 thisQuery.LargeMP4 = largerMp4.Success;
\r
199 thisQuery.IpodAtom = ipodAtom.Success;
\r
200 thisQuery.OptimizeMP4 = optimizeMP4.Success;
\r
204 #region Picture Tab
\r
207 thisQuery.Width = int.Parse(width.Groups[0].Value.Replace("-w ", ""));
\r
209 if (height.Success)
\r
210 thisQuery.Height = int.Parse(height.Groups[0].Value.Replace("-l ", ""));
\r
212 if (maxWidth.Success)
\r
213 thisQuery.MaxWidth = int.Parse(maxWidth.Groups[0].Value.Replace("-X ", ""));
\r
215 if (maxHeight.Success)
\r
216 thisQuery.MaxHeight = int.Parse(maxHeight.Groups[0].Value.Replace("-Y ", ""));
\r
220 thisQuery.CropValues = crop.ToString().Replace("--crop ", "");
\r
221 string[] actCropValues = thisQuery.CropValues.Split(':');
\r
222 thisQuery.CropTop = actCropValues[0];
\r
223 thisQuery.CropBottom = actCropValues[1];
\r
224 thisQuery.CropLeft = actCropValues[2];
\r
225 thisQuery.CropRight = actCropValues[3];
\r
228 if (strictAnamorphic.Success)
\r
229 thisQuery.AnamorphicMode = 1;
\r
230 else if (looseAnamorphic.Success)
\r
231 thisQuery.AnamorphicMode = 2;
\r
232 else if (customAnamorphic.Success)
\r
233 thisQuery.AnamorphicMode = 3;
\r
235 thisQuery.AnamorphicMode = 0;
\r
237 thisQuery.keepDisplayAsect = keepDisplayAsect.Success;
\r
239 if (displayWidth.Success)
\r
240 thisQuery.displayWidthValue = double.Parse(displayWidth.Groups[0].Value.Replace("--display-width ", ""));
\r
242 if (pixelAspect.Success)
\r
243 thisQuery.pixelAspectWidth = int.Parse(pixelAspect.Groups[1].Value.Replace("--pixel-aspect ", ""));
\r
245 if (pixelAspect.Success && pixelAspect.Groups.Count >=3)
\r
246 thisQuery.pixelAspectHeight = int.Parse(pixelAspect.Groups[2].Value.Replace("--pixel-aspect ", ""));
\r
248 if (modulus.Success)
\r
249 thisQuery.AnamorphicModulus = int.Parse(modulus.Groups[0].Value.Replace("--modulus ", ""));
\r
256 thisQuery.Decomb = "Off";
\r
257 if (decomb.Success)
\r
259 thisQuery.Decomb = "Default";
\r
260 if (decombValue.Success)
\r
261 thisQuery.Decomb = decombValue.ToString().Replace("--decomb=", "").Replace("\"", "");
\r
264 thisQuery.DeInterlace = "Off";
\r
265 if (deinterlace.Success)
\r
267 thisQuery.DeInterlace = deinterlace.ToString().Replace("--deinterlace=", "").Replace("\"", "");
\r
268 thisQuery.DeInterlace = thisQuery.DeInterlace.Replace("fast", "Fast").Replace("slow", "Slow").Replace("slower", "Slower");
\r
269 thisQuery.DeInterlace = thisQuery.DeInterlace.Replace("slowest", "Slowest");
\r
272 thisQuery.DeNoise = "Off";
\r
273 if (denoise.Success)
\r
275 thisQuery.DeNoise = denoise.ToString().Replace("--denoise=", "").Replace("\"", "");
\r
276 thisQuery.DeNoise = thisQuery.DeNoise.Replace("weak", "Weak").Replace("medium", "Medium").Replace("strong", "Strong");
\r
279 string deblockValue = "";
\r
280 thisQuery.DeBlock = 0;
\r
281 if (deblock.Success)
\r
282 deblockValue = deblock.ToString().Replace("--deblock=", "");
\r
285 if (deblockValue != "")
\r
286 int.TryParse(deblockValue, out dval);
\r
287 thisQuery.DeBlock = dval;
\r
289 thisQuery.DeTelecine = "Off";
\r
290 if (detelecine.Success)
\r
292 thisQuery.DeTelecine = "Default";
\r
293 if (detelecineValue.Success)
\r
294 thisQuery.DeTelecine = detelecineValue.ToString().Replace("--detelecine=", "").Replace("\"", "");
\r
299 #region Video Settings Tab
\r
301 string videoEncoderConvertion = videoEncoder.ToString().Replace("-e ", "");
\r
302 switch (videoEncoderConvertion)
\r
305 videoEncoderConvertion = "MPEG-4 (FFmpeg)";
\r
308 videoEncoderConvertion = "H.264 (x264)";
\r
311 videoEncoderConvertion = "VP3 (Theora)";
\r
314 videoEncoderConvertion = "MPEG-4 (FFmpeg)";
\r
317 thisQuery.VideoEncoder = videoEncoderConvertion;
\r
318 thisQuery.VideoFramerate = videoFramerate.Success ? videoFramerate.ToString().Replace("-r ", "") : "Same as source";
\r
319 thisQuery.Grayscale = grayscale.Success;
\r
320 thisQuery.TwoPass = twoPass.Success;
\r
321 thisQuery.TurboFirstPass = turboFirstPass.Success;
\r
323 if (videoBitrate.Success)
\r
324 thisQuery.AverageVideoBitrate = videoBitrate.ToString().Replace("-b ", "");
\r
325 if (videoFilesize.Success)
\r
326 thisQuery.VideoTargetSize = videoFilesize.ToString().Replace("-S ", "");
\r
328 if (videoQuality.Success)
\r
330 float qConvert = float.Parse(videoQuality.ToString().Replace("-q ", ""), Culture);
\r
331 thisQuery.VideoQuality = qConvert;
\r
334 thisQuery.VideoQuality = -1;
\r
338 // Find out how many tracks we need to add by checking how many encoders or audio tracks are selected.
\r
339 int encoderCount = 0;
\r
340 if (audioEncoders.Success)
\r
342 string[] audioDataCounters = audioEncoders.ToString().Replace("-E ", "").Split(',');
\r
343 encoderCount = audioDataCounters.Length;
\r
346 // Get the data from the regular expression results
\r
347 string[] trackData = null;
\r
348 string[] trackMixes = null;
\r
349 string[] trackEncoders = null;
\r
350 string[] trackBitrates = null;
\r
351 string[] trackSamplerates = null;
\r
352 string[] trackDRCvalues = null;
\r
354 if (audioTracks.Success)
\r
355 trackData = audioTracks.ToString().Replace("-a ", "").Split(',');
\r
356 if (audioTrackMixes.Success)
\r
357 trackMixes = audioTrackMixes.ToString().Replace("-6 ", "").Split(',');
\r
358 if (audioEncoders.Success)
\r
359 trackEncoders = audioEncoders.ToString().Replace("-E ", "").Split(',');
\r
360 if (audioBitrates.Success)
\r
361 trackBitrates = audioBitrates.ToString().Replace("-B ", "").Split(',');
\r
362 if (audioSampleRates.Success)
\r
363 trackSamplerates = audioSampleRates.ToString().Replace("-R ", "").Split(',');
\r
364 if (drcValues.Success)
\r
365 trackDRCvalues = drcValues.ToString().Replace("-D ", "").Split(',');
\r
367 // Create new Audio Track Classes and store them in the ArrayList
\r
368 ArrayList AllAudioTrackInfo = new ArrayList();
\r
369 for (int x = 0; x < encoderCount; x++)
\r
371 AudioTrack track = new AudioTrack();
\r
372 if (trackData != null)
\r
373 if (trackData.Length >= (x + 1)) // Audio Track
\r
374 track.Track = trackData[x].Trim();
\r
376 if (trackMixes != null)
\r
377 if (trackMixes.Length >= (x + 1)) // Audio Mix
\r
378 track.MixDown = getMixDown(trackMixes[x].Trim());
\r
380 if (trackEncoders != null)
\r
381 if (trackEncoders.Length >= (x + 1)) // Audio Mix
\r
382 track.Encoder = getAudioEncoder(trackEncoders[x].Trim());
\r
384 if (trackBitrates != null)
\r
385 if (trackBitrates.Length >= (x + 1)) // Audio Encoder
\r
386 track.Bitrate = trackBitrates[x].Trim() == "auto" ? "Auto" : trackBitrates[x].Trim();
\r
388 if (trackSamplerates != null)
\r
389 if (trackSamplerates.Length >= (x + 1)) // Audio SampleRate
\r
390 track.SampleRate = trackSamplerates[x].Trim() == "0" ? "Auto" : trackSamplerates[x].Trim();
\r
392 if (trackDRCvalues != null)
\r
393 if (trackDRCvalues.Length >= (x + 1)) // Audio DRC Values
\r
394 track.DRC = trackDRCvalues[x].Trim();
\r
396 AllAudioTrackInfo.Add(track);
\r
398 thisQuery.AudioInformation = AllAudioTrackInfo;
\r
401 if (subtitles.Success)
\r
402 thisQuery.Subtitles = subtitles.ToString().Replace("-s ", "");
\r
404 thisQuery.Subtitles = subScan.Success ? "Autoselect" : "None";
\r
406 thisQuery.ForcedSubtitles = forcedSubtitles.Success;
\r
409 #region Chapters Tab
\r
410 if (chapterMarkersFileMode.Success || chapterMarkers.Success)
\r
411 thisQuery.ChapterMarkers = true;
\r
414 #region H.264 and other
\r
417 thisQuery.H264Query = x264.ToString().Replace("-x ", "");
\r
419 thisQuery.Verbose = verbose.Success;
\r
423 catch (Exception exc)
\r
426 "An error has occured in the Query Parser. Please report this error on the forum in the 'Windows' support section. \n\n" +
\r
427 exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
434 private static string getMixDown(string mixdown)
\r
436 switch (mixdown.Trim())
\r
443 return "Dolby Surround";
\r
445 return "Dolby Pro Logic II";
\r
447 return "6 Channel Discrete";
\r
449 return "Automatic";
\r
452 private static string getAudioEncoder(string audioEnc)
\r
457 return "AAC (faac)";
\r
459 return "MP3 (lame)";
\r
461 return "Vorbis (vorbis)";
\r
463 return "AC3 Passthru";
\r
465 return "DTS Passthru";
\r
467 return "AAC (faac)";
\r
472 public class AudioTrack
\r
474 public AudioTrack()
\r
477 Track = "Automatic";
\r
478 MixDown = "Automatic";
\r
479 SampleRate = "Auto";
\r
483 public string Track { get; set; }
\r
484 public string MixDown { get; set; }
\r
485 public string Encoder { get; set; }
\r
486 public string Bitrate { get; set; }
\r
487 public string SampleRate { get; set; }
\r
488 public string DRC { get; set; }
\r