1 /* PlistPresetHandler.cs $
\r
2 This file is part of the HandBrake source code.
\r
3 Homepage: <http://handbrake.fr/>.
\r
4 It may be used under the terms of the GNU General Public License. */
\r
6 namespace Handbrake.Presets
\r
9 using System.Collections;
\r
12 using System.Windows.Forms;
\r
18 /// Plist Preset Converter
\r
20 public class PlistPresetHandler
\r
24 public static QueryParser Import(string filename)
\r
26 XmlNode root = loadFile(filename);
\r
27 if (root == null) return null;
\r
29 // We'll query a query parser object and use it's public var structures to store all the data.
\r
30 // This will allow the preset loader logic to be used instead of writing custom logic just for this file.
\r
31 QueryParser queryParsed = new QueryParser();
\r
32 string qualityMode = string.Empty;
\r
34 #region Get a List of Audio Track Objects
\r
35 XmlNode audioListDict = root.ChildNodes[2].ChildNodes[0].FirstChild.ChildNodes[1];
\r
36 ArrayList audioTracks = new ArrayList();
\r
38 for (int i = 0; i < audioListDict.ChildNodes.Count; i++)
\r
40 XmlNode audioChannel = audioListDict.ChildNodes[i];
\r
41 AudioTrack track = new AudioTrack();
\r
43 for (int subi = 0; subi < audioChannel.ChildNodes.Count; subi += 2)
\r
45 // Audio Channel Information is here.
\r
46 string key = audioChannel.ChildNodes[subi].InnerText;
\r
47 string value = audioChannel.ChildNodes[subi + 1].InnerText;
\r
50 case "AudioBitrate":
\r
51 track.Bitrate = value;
\r
53 case "AudioEncoder":
\r
54 track.Encoder = value.Replace("AAC (CoreAudio)", "AAC (faac)");
\r
56 case "AudioMixdown":
\r
57 track.MixDown = value;
\r
59 case "AudioSamplerate":
\r
60 track.SampleRate = value;
\r
63 track.Track = value;
\r
65 case "AudioTrackDRCSlider":
\r
70 audioTracks.Add(track);
\r
71 queryParsed.AudioInformation = audioTracks;
\r
75 #region Parse the reset of the plist keys into local variables
\r
77 XmlNode presetSettings = root.ChildNodes[2].ChildNodes[0].FirstChild;
\r
79 // Start from 2 to avoid the audio settings which we don't need.
\r
80 for (int i = 2; i < presetSettings.ChildNodes.Count; i += 2)
\r
82 string key = presetSettings.ChildNodes[i].InnerText;
\r
83 string value = presetSettings.ChildNodes[i + 1].InnerText;
\r
89 queryParsed.Format = value;
\r
91 case "Mp4HttpOptimize":
\r
92 queryParsed.OptimizeMP4 = value == "1";
\r
94 case "Mp4LargeFile":
\r
95 queryParsed.LargeMP4 = value == "1";
\r
97 case "Mp4iPodCompatible":
\r
98 queryParsed.IpodAtom = value == "1";
\r
101 // Picture Settings
\r
102 case "PictureAutoCrop":
\r
105 case "PictureTopCrop":
\r
106 queryParsed.CropTop = value;
\r
108 case "PictureBottomCrop":
\r
109 queryParsed.CropBottom = value;
\r
111 case "PictureLeftCrop":
\r
112 queryParsed.CropLeft = value;
\r
114 case "PictureRightCrop":
\r
115 queryParsed.CropRight = value;
\r
117 case "PictureHeight":
\r
118 queryParsed.Height = int.Parse(value);
\r
120 case "PictureWidth":
\r
121 queryParsed.Width = int.Parse(value);
\r
123 case "PictureKeepRatio":
\r
124 queryParsed.KeepDisplayAsect = value == "1";
\r
127 queryParsed.AnamorphicMode = int.Parse(value);
\r
131 case "PictureDeblock":
\r
132 queryParsed.DeBlock = int.Parse(value);
\r
134 case "PictureDecomb":
\r
135 queryParsed.Decomb = "Off";
\r
136 // Don't place custom here as it's handled in the filter panel
\r
137 if (value == "2") queryParsed.Decomb = "Default";
\r
139 case "PictureDecombCustom":
\r
140 if (value != string.Empty)
\r
141 queryParsed.Decomb = value;
\r
143 case "PictureDecombDeinterlace":
\r
146 case "PictureDeinterlace":
\r
150 queryParsed.DeInterlace = "Off";
\r
152 // Don't place custom here as it's handled in the filter panel
\r
154 queryParsed.DeInterlace = "Fast";
\r
157 queryParsed.DeInterlace = "Slow";
\r
160 queryParsed.DeInterlace = "Slowest";
\r
164 case "PictureDeinterlaceCustom":
\r
165 if (value != string.Empty)
\r
166 queryParsed.DeInterlace = value;
\r
168 case "PictureDenoise":
\r
172 queryParsed.DeNoise = "Off";
\r
174 // Don't place custom here as it's handled in the filter panel
\r
176 queryParsed.DeNoise = "Weak";
\r
179 queryParsed.DeNoise = "Medium";
\r
182 queryParsed.DeNoise = "Strong";
\r
187 case "PictureDenoiseCustom":
\r
188 if (value != string.Empty)
\r
189 queryParsed.DeNoise = value;
\r
191 case "PictureDetelecine":
\r
192 queryParsed.DeTelecine = "Off";
\r
193 if (value == "1") queryParsed.DeTelecine = "Default";
\r
195 case "PictureDetelecineCustom":
\r
196 if (value != string.Empty)
\r
197 queryParsed.DeTelecine = value;
\r
201 case "VideoAvgBitrate":
\r
202 queryParsed.AverageVideoBitrate = value;
\r
204 case "VideoEncoder":
\r
205 queryParsed.VideoEncoder = value;
\r
207 case "VideoFramerate":
\r
208 queryParsed.VideoFramerate = value;
\r
210 case "VideoGrayScale":
\r
211 queryParsed.Grayscale = value == "1";
\r
213 case "VideoQualitySlider":
\r
214 queryParsed.VideoQuality = float.Parse(value);
\r
216 case "VideoQualityType": // The Type of Quality Mode used
\r
217 qualityMode = value;
\r
219 case "VideoTargetSize":
\r
220 queryParsed.VideoTargetSize = value;
\r
222 case "VideoTurboTwoPass":
\r
223 queryParsed.TurboFirstPass = value == "1";
\r
225 case "VideoTwoPass":
\r
226 queryParsed.TwoPass = value == "1";
\r
229 // Chapter Markers Tab
\r
230 case "ChapterMarkers":
\r
231 queryParsed.ChapterMarkers = value == "1";
\r
234 // Advanced x264 tab
\r
236 queryParsed.H264Query = value;
\r
239 // Preset Information
\r
240 case "PresetBuildNumber":
\r
241 queryParsed.PresetBuildNumber = int.Parse(value);
\r
243 case "PresetDescription":
\r
244 queryParsed.PresetDescription = value;
\r
247 queryParsed.PresetName = value;
\r
250 queryParsed.Type = value;
\r
252 case "UsesMaxPictureSettings":
\r
253 queryParsed.UsesMaxPictureSettings = value == "1";
\r
255 case "UsesPictureFilters":
\r
256 queryParsed.UsesPictureFilters = value == "1";
\r
258 case "UsesPictureSettings":
\r
259 queryParsed.UsesPictureSettings = value == "1";
\r
264 // Kill any Quality values we don't need.
\r
265 switch (qualityMode)
\r
267 case "0": // FileSize
\r
268 queryParsed.VideoQuality = -1;
\r
269 queryParsed.AverageVideoBitrate = null;
\r
271 case "1": // Avg Bitrate
\r
272 queryParsed.VideoQuality = -1;
\r
273 queryParsed.VideoTargetSize = null;
\r
276 queryParsed.AverageVideoBitrate = null;
\r
277 queryParsed.VideoTargetSize = null;
\r
282 return queryParsed;
\r
285 private static XmlNode loadFile(string filename)
\r
291 if (!File.Exists(filename))
\r
294 StreamReader sr = File.OpenText(filename);
\r
295 string fromfile = string.Empty;
\r
297 while ((fileChar = sr.Read()) != -1)
\r
298 fromfile += Convert.ToChar(fileChar);
\r
300 XmlDocument doc = new XmlDocument();
\r
301 doc.LoadXml(fromfile);
\r
304 if (!root.HasChildNodes)
\r
307 "The Preset file you selected appears to be invlaid or from an older version of HandBrake",
\r
309 MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
318 "The Preset file you selected appears to be invlaid or from an older version of HandBrake.\n\n Please note, if you are exporting from the MacGui you may need to rebuild your preset so that it uses the current preset plist format.\n The MacGui does not currently update user presets automatically.",
\r
320 MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
329 /// Export a MacGui style plist preset.
\r
331 /// <param name="path">
\r
334 /// <param name="preset">
\r
337 public static void Export(string path, Preset preset)
\r
339 QueryParser parsed = QueryParser.Parse(preset.Query);
\r
341 XmlTextWriter xmlWriter;
\r
343 xmlWriter = new XmlTextWriter(path, Encoding.UTF8);
\r
346 xmlWriter.WriteStartDocument();
\r
347 xmlWriter.WriteDocType("plist", "-//Apple//DTD PLIST 1.0//EN",
\r
348 @"http://www.apple.com/DTDs/PropertyList-1.0.dtd", null);
\r
350 xmlWriter.WriteStartElement("plist");
\r
351 xmlWriter.WriteStartElement("array");
\r
353 // Add New Preset Here. Can write multiple presets here if required in future.
\r
354 WritePreset(xmlWriter, parsed, preset);
\r
357 xmlWriter.WriteEndElement();
\r
358 xmlWriter.WriteEndElement();
\r
360 xmlWriter.WriteEndDocument();
\r
367 /// Write the Preset to a file
\r
369 /// <param name="xmlWriter">
\r
370 /// The xml writer.
\r
372 /// <param name="parsed">
\r
375 /// <param name="preset">
\r
378 private static void WritePreset(XmlTextWriter xmlWriter, QueryParser parsed, Preset preset)
\r
380 xmlWriter.WriteStartElement("dict");
\r
381 AudioListArrayDict(xmlWriter, parsed);
\r
382 AddEncodeSettings(xmlWriter, parsed, preset);
\r
384 xmlWriter.WriteEndElement();
\r
388 /// Add the encode settings to the preset
\r
390 /// <param name="xmlWriter">
\r
391 /// The xml writer.
\r
393 /// <param name="parsed">
\r
396 /// <param name="preset">
\r
399 private static void AddEncodeSettings(XmlTextWriter xmlWriter, QueryParser parsed, Preset preset)
\r
401 AddEncodeElement(xmlWriter, "ChapterMarkers", "integer", parsed.ChapterMarkers ? "1" : "0");
\r
402 AddEncodeElement(xmlWriter, "Default", "integer", string.Empty); // TODO
\r
403 AddEncodeElement(xmlWriter, "FileFormat", "string", parsed.Format);
\r
404 AddBooleanElement(xmlWriter, "Folder", false); // TODO
\r
405 AddEncodeElement(xmlWriter, "Mp4HttpOptimize", "integer", parsed.OptimizeMP4 ? "1" : "0");
\r
406 AddEncodeElement(xmlWriter, "Mp4LargeFile", "integer", parsed.LargeMP4 ? "1" : "0");
\r
407 AddEncodeElement(xmlWriter, "Mp4iPodCompatible", "integer", parsed.IpodAtom ? "1" : "0");
\r
408 AddEncodeElement(xmlWriter, "PictureAutoCrop", "integer", "1"); // TODO
\r
409 AddEncodeElement(xmlWriter, "PictureBottomCrop", "integer", parsed.CropBottom);
\r
411 // Filters - TODO Requires Some Logic to convert modes
\r
412 AddEncodeElement(xmlWriter, "PictureDeblock", "integer", parsed.DeBlock.ToString());
\r
414 switch (parsed.Decomb)
\r
417 AddEncodeElement(xmlWriter, "PictureDecomb", "integer", "0");
\r
418 AddEncodeElement(xmlWriter, "PictureDecombCustom", "string", string.Empty);
\r
421 AddEncodeElement(xmlWriter, "PictureDecomb", "integer", "1");
\r
422 AddEncodeElement(xmlWriter, "PictureDecombCustom", "string", string.Empty);
\r
425 AddEncodeElement(xmlWriter, "PictureDecomb", "integer", "2");
\r
426 AddEncodeElement(xmlWriter, "PictureDecombCustom", "string", parsed.Decomb);
\r
429 AddEncodeElement(xmlWriter, "PictureDecombDeinterlace", "integer", parsed.Decomb != "Off" ? "0" : "1");
\r
431 switch (parsed.DeInterlace)
\r
434 AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", "0");
\r
435 AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", string.Empty);
\r
438 AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", "1");
\r
439 AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", string.Empty);
\r
442 AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", "2");
\r
443 AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", string.Empty);
\r
446 AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", "3");
\r
447 AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", string.Empty);
\r
450 AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", "4");
\r
451 AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", parsed.DeInterlace);
\r
455 switch (parsed.DeNoise)
\r
458 AddEncodeElement(xmlWriter, "PictureDenoise", "integer", "0");
\r
459 AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", string.Empty);
\r
462 AddEncodeElement(xmlWriter, "PictureDenoise", "integer", "1");
\r
463 AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", string.Empty);
\r
466 AddEncodeElement(xmlWriter, "PictureDenoise", "integer", "2");
\r
467 AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", string.Empty);
\r
470 AddEncodeElement(xmlWriter, "PictureDenoise", "integer", "3");
\r
471 AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", string.Empty);
\r
474 AddEncodeElement(xmlWriter, "PictureDenoise", "integer", "4");
\r
475 AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", parsed.DeNoise);
\r
480 switch (parsed.DeTelecine)
\r
492 AddEncodeElement(xmlWriter, "PictureDetelecine", "integer", detelecine.ToString());
\r
493 AddEncodeElement(xmlWriter, "PictureDetelecineCustom", "string", detelecine == 1 ? parsed.DeTelecine : string.Empty);
\r
495 // Picture Settings
\r
496 AddEncodeElement(xmlWriter, "PictureHeight", "integer", parsed.Height.ToString());
\r
497 AddEncodeElement(xmlWriter, "PictureKeepRatio", "integer", parsed.KeepDisplayAsect ? "1" : "0");
\r
498 AddEncodeElement(xmlWriter, "PictureLeftCrop", "integer", parsed.CropLeft);
\r
499 AddEncodeElement(xmlWriter, "PicturePAR", "integer", parsed.AnamorphicMode.ToString());
\r
500 AddEncodeElement(xmlWriter, "PictureRightCrop", "integer", parsed.CropRight);
\r
501 AddEncodeElement(xmlWriter, "PictureTopCrop", "integer", parsed.CropTop);
\r
502 AddEncodeElement(xmlWriter, "PictureWidth", "integer", parsed.Width.ToString());
\r
504 // Preset Information
\r
505 AddEncodeElement(xmlWriter, "PresetBuildNumber", "string", Properties.Settings.Default.hb_build.ToString());
\r
506 AddEncodeElement(xmlWriter, "PresetDescription", "string", "No Description");
\r
507 AddEncodeElement(xmlWriter, "PresetName", "string", preset.Name);
\r
508 AddEncodeElement(xmlWriter, "Type", "integer", "1"); // 1 is user preset, 0 is built in
\r
511 AddEncodeElement(xmlWriter, "UsesMaxPictureSettings", "integer", (parsed.MaxWidth != 0 || parsed.MaxHeight != 0).ToString());
\r
512 AddEncodeElement(xmlWriter, "UsesPictureFilters", "integer", "True");
\r
513 AddEncodeElement(xmlWriter, "UsesPictureSettings", "integer", "True");
\r
516 AddEncodeElement(xmlWriter, "VideoAvgBitrate", "string", parsed.AverageVideoBitrate);
\r
517 AddEncodeElement(xmlWriter, "VideoEncoder", "string", parsed.VideoEncoder);
\r
518 AddEncodeElement(xmlWriter, "VideoFramerate", "string", parsed.VideoFramerate);
\r
519 AddEncodeElement(xmlWriter, "VideoGrayScale", "integer", parsed.Grayscale ? "1" : "0");
\r
520 AddEncodeElement(xmlWriter, "VideoQualitySlider", "real", parsed.VideoQuality.ToString());
\r
522 int videoQualityType = 0;
\r
523 if (!string.IsNullOrEmpty(parsed.VideoTargetSize)) videoQualityType = 0;
\r
524 else if (!string.IsNullOrEmpty(parsed.AverageVideoBitrate)) videoQualityType = 1;
\r
525 else if (parsed.VideoQuality != 0) videoQualityType = 2;
\r
527 AddEncodeElement(xmlWriter, "VideoQualityType", "integer", videoQualityType.ToString());
\r
528 AddEncodeElement(xmlWriter, "VideoTargetSize", "string", parsed.VideoTargetSize);
\r
529 AddEncodeElement(xmlWriter, "VideoTurboTwoPass", "integer", parsed.TurboFirstPass ? "1" : "0");
\r
530 AddEncodeElement(xmlWriter, "VideoTwoPass", "integer", parsed.TwoPass ? "1" : "0");
\r
533 AddEncodeElement(xmlWriter, "x264Option", "string", parsed.H264Query);
\r
537 /// Add a boolean element
\r
539 /// <param name="xmlWriter">
\r
540 /// The xml writer.
\r
542 /// <param name="keyName">
\r
545 /// <param name="value">
\r
548 private static void AddBooleanElement(XmlTextWriter xmlWriter, string keyName, bool value)
\r
550 xmlWriter.WriteStartElement("key");
\r
551 xmlWriter.WriteString(keyName);
\r
552 xmlWriter.WriteEndElement();
\r
555 xmlWriter.WriteStartElement("true");
\r
556 xmlWriter.WriteEndElement();
\r
560 xmlWriter.WriteStartElement("false");
\r
561 xmlWriter.WriteEndElement();
\r
566 /// Add an encode setting element
\r
568 /// <param name="xmlWriter">
\r
569 /// The xml writer.
\r
571 /// <param name="keyName">
\r
574 /// <param name="type">
\r
577 /// <param name="value">
\r
580 private static void AddEncodeElement(XmlTextWriter xmlWriter, string keyName, string type, string value)
\r
582 xmlWriter.WriteElementString("key", keyName);
\r
583 xmlWriter.WriteElementString(type, value);
\r
587 /// Add an Audio Track Array Dict
\r
589 /// <param name="xmlWriter">
\r
590 /// The xml writer.
\r
592 /// <param name="parsed">
\r
595 private static void AudioListArrayDict(XmlTextWriter xmlWriter, QueryParser parsed)
\r
597 xmlWriter.WriteStartElement("key");
\r
598 xmlWriter.WriteString("AudioList");
\r
599 xmlWriter.WriteEndElement();
\r
601 xmlWriter.WriteStartElement("array");
\r
602 foreach (AudioTrack track in parsed.AudioInformation)
\r
604 AddAudioItem(xmlWriter, track);
\r
606 xmlWriter.WriteEndElement();
\r
610 /// Add an audio track
\r
612 /// <param name="xmlWriter">
\r
613 /// The xml writer.
\r
615 /// <param name="audioTrack">
\r
616 /// The audio track.
\r
618 private static void AddAudioItem(XmlTextWriter xmlWriter, AudioTrack audioTrack)
\r
620 string bitrate = audioTrack.Bitrate;
\r
621 string encoder = audioTrack.Encoder;
\r
622 string mixdown = audioTrack.MixDown;
\r
623 string sample = audioTrack.SampleRate;
\r
625 int.TryParse(audioTrack.Track, out track);
\r
626 string drc = audioTrack.DRC;
\r
627 string desc = "Automatic";
\r
629 xmlWriter.WriteStartElement("dict");
\r
631 xmlWriter.WriteElementString("key", "AudioBitrate");
\r
632 xmlWriter.WriteElementString("string", bitrate);
\r
634 xmlWriter.WriteElementString("key", "AudioEncoder");
\r
635 xmlWriter.WriteElementString("string", encoder);
\r
637 xmlWriter.WriteElementString("key", "AudioMixdown");
\r
638 xmlWriter.WriteElementString("string", mixdown);
\r
640 xmlWriter.WriteElementString("key", "AudioSamplerate");
\r
641 xmlWriter.WriteElementString("string", sample);
\r
643 xmlWriter.WriteElementString("key", "AudioTrack");
\r
644 xmlWriter.WriteElementString("integer", track.ToString());
\r
646 xmlWriter.WriteElementString("key", "AudioTrackDRCSlider");
\r
647 xmlWriter.WriteElementString("real", drc);
\r
649 xmlWriter.WriteElementString("key", "AudioTrackDescription");
\r
650 xmlWriter.WriteElementString("string", desc);
\r
652 xmlWriter.WriteEndElement();
\r