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
35 #region Get a List of Audio Track Objects
\r
36 XmlNode audioListDict = root.ChildNodes[2].ChildNodes[0].FirstChild.ChildNodes[1];
\r
37 ArrayList audioTracks = new ArrayList();
\r
39 for (int i = 0; i < audioListDict.ChildNodes.Count; i++)
\r
41 XmlNode audioChannel = audioListDict.ChildNodes[i];
\r
42 AudioTrack track = new AudioTrack();
\r
44 for (int subi = 0; subi < audioChannel.ChildNodes.Count; subi += 2)
\r
46 // Audio Channel Information is here.
\r
47 string key = audioChannel.ChildNodes[subi].InnerText;
\r
48 string value = audioChannel.ChildNodes[subi + 1].InnerText;
\r
51 case "AudioBitrate":
\r
52 track.Bitrate = value;
\r
54 case "AudioEncoder":
\r
55 track.Encoder = value.Replace("AAC (CoreAudio)", "AAC (faac)");
\r
57 case "AudioMixdown":
\r
58 track.MixDown = value;
\r
60 case "AudioSamplerate":
\r
61 track.SampleRate = value;
\r
64 track.Track = value;
\r
66 case "AudioTrackDRCSlider":
\r
71 audioTracks.Add(track);
\r
72 queryParsed.AudioInformation = audioTracks;
\r
76 #region Parse the reset of the plist keys into local variables
\r
78 XmlNode presetSettings = root.ChildNodes[2].ChildNodes[0].FirstChild;
\r
80 // Start from 2 to avoid the audio settings which we don't need.
\r
81 for (int i = 2; i < presetSettings.ChildNodes.Count; i += 2)
\r
83 string key = presetSettings.ChildNodes[i].InnerText;
\r
84 string value = presetSettings.ChildNodes[i + 1].InnerText;
\r
90 queryParsed.Format = value;
\r
92 case "Mp4HttpOptimize":
\r
93 queryParsed.OptimizeMP4 = value == "1";
\r
95 case "Mp4LargeFile":
\r
96 queryParsed.LargeMP4 = value == "1";
\r
98 case "Mp4iPodCompatible":
\r
99 queryParsed.IpodAtom = value == "1";
\r
102 // Picture Settings
\r
103 case "PictureAutoCrop":
\r
106 case "PictureTopCrop":
\r
107 queryParsed.CropTop = value;
\r
109 case "PictureBottomCrop":
\r
110 queryParsed.CropBottom = value;
\r
112 case "PictureLeftCrop":
\r
113 queryParsed.CropLeft = value;
\r
115 case "PictureRightCrop":
\r
116 queryParsed.CropRight = value;
\r
118 case "PictureHeight":
\r
119 queryParsed.Height = int.Parse(value);
\r
121 case "PictureWidth":
\r
122 queryParsed.Width = int.Parse(value);
\r
124 case "PictureKeepRatio":
\r
125 queryParsed.KeepDisplayAsect = value == "1";
\r
128 queryParsed.AnamorphicMode = int.Parse(value);
\r
132 case "PictureDeblock":
\r
133 queryParsed.DeBlock = int.Parse(value);
\r
135 case "PictureDecomb":
\r
136 queryParsed.Decomb = "Off";
\r
137 // Don't place custom here as it's handled in the filter panel
\r
138 if (value == "2") queryParsed.Decomb = "Default";
\r
140 case "PictureDecombCustom":
\r
141 if (value != string.Empty)
\r
142 queryParsed.Decomb = value;
\r
144 case "PictureDecombDeinterlace":
\r
147 case "PictureDeinterlace":
\r
151 queryParsed.DeInterlace = "Off";
\r
153 // Don't place custom here as it's handled in the filter panel
\r
155 queryParsed.DeInterlace = "Fast";
\r
158 queryParsed.DeInterlace = "Slow";
\r
161 queryParsed.DeInterlace = "Slowest";
\r
165 case "PictureDeinterlaceCustom":
\r
166 if (value != string.Empty)
\r
167 queryParsed.DeInterlace = value;
\r
169 case "PictureDenoise":
\r
173 queryParsed.DeNoise = "Off";
\r
175 // Don't place custom here as it's handled in the filter panel
\r
177 queryParsed.DeNoise = "Weak";
\r
180 queryParsed.DeNoise = "Medium";
\r
183 queryParsed.DeNoise = "Strong";
\r
188 case "PictureDenoiseCustom":
\r
189 if (value != string.Empty)
\r
190 queryParsed.DeNoise = value;
\r
192 case "PictureDetelecine":
\r
193 queryParsed.DeTelecine = "Off";
\r
194 if (value == "1") queryParsed.DeTelecine = "Default";
\r
196 case "PictureDetelecineCustom":
\r
197 if (value != string.Empty)
\r
198 queryParsed.DeTelecine = value;
\r
202 case "VideoAvgBitrate":
\r
203 queryParsed.AverageVideoBitrate = value;
\r
205 case "VideoEncoder":
\r
206 queryParsed.VideoEncoder = value;
\r
208 case "VideoFramerate":
\r
209 queryParsed.VideoFramerate = value;
\r
211 case "VideoGrayScale":
\r
212 queryParsed.Grayscale = value == "1";
\r
214 case "VideoQualitySlider":
\r
215 queryParsed.VideoQuality = float.Parse(value);
\r
217 case "VideoQualityType": // The Type of Quality Mode used
\r
218 qualityMode = value;
\r
220 case "VideoTargetSize":
\r
221 queryParsed.VideoTargetSize = value;
\r
223 case "VideoTurboTwoPass":
\r
224 queryParsed.TurboFirstPass = value == "1";
\r
226 case "VideoTwoPass":
\r
227 queryParsed.TwoPass = value == "1";
\r
230 // Chapter Markers Tab
\r
231 case "ChapterMarkers":
\r
232 queryParsed.ChapterMarkers = value == "1";
\r
235 // Advanced x264 tab
\r
237 queryParsed.H264Query = value;
\r
240 // Preset Information
\r
241 case "PresetBuildNumber":
\r
242 queryParsed.PresetBuildNumber = int.Parse(value);
\r
244 case "PresetDescription":
\r
245 queryParsed.PresetDescription = value;
\r
248 queryParsed.PresetName = value;
\r
251 queryParsed.Type = value;
\r
253 case "UsesMaxPictureSettings":
\r
254 queryParsed.UsesMaxPictureSettings = value == "1";
\r
256 case "UsesPictureFilters":
\r
257 queryParsed.UsesPictureFilters = value == "1";
\r
259 case "UsesPictureSettings":
\r
260 queryParsed.UsesPictureSettings = value == "1";
\r
265 // Kill any Quality values we don't need.
\r
266 switch (qualityMode)
\r
268 case "0": // FileSize
\r
269 queryParsed.VideoQuality = -1;
\r
270 queryParsed.AverageVideoBitrate = null;
\r
272 case "1": // Avg Bitrate
\r
273 queryParsed.VideoQuality = -1;
\r
274 queryParsed.VideoTargetSize = null;
\r
277 queryParsed.AverageVideoBitrate = null;
\r
278 queryParsed.VideoTargetSize = null;
\r
283 return queryParsed;
\r
286 private static XmlNode loadFile(string filename)
\r
292 if (!File.Exists(filename))
\r
295 StreamReader sr = File.OpenText(filename);
\r
296 string fromfile = string.Empty;
\r
298 while ((fileChar = sr.Read()) != -1)
\r
299 fromfile += Convert.ToChar(fileChar);
\r
301 XmlDocument doc = new XmlDocument();
\r
302 doc.LoadXml(fromfile);
\r
305 if (!root.HasChildNodes)
\r
308 "The Preset file you selected appears to be invlaid or from an older version of HandBrake",
\r
310 MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
319 "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
321 MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
329 public static void Export(string path, QueryParser parsed)
\r
331 XmlTextWriter xmlWriter;
\r
333 xmlWriter = new XmlTextWriter(path, Encoding.UTF8);
\r
336 xmlWriter.WriteStartDocument();
\r
337 xmlWriter.WriteDocType("plist", "-//Apple//DTD PLIST 1.0//EN",
\r
338 @"http://www.apple.com/DTDs/PropertyList-1.0.dtd", null);
\r
340 xmlWriter.WriteStartElement("plist");
\r
341 xmlWriter.WriteStartElement("array");
\r
343 // Add New Preset Here. Can write multiple presets here if required in future.
\r
344 WritePreset(xmlWriter, parsed);
\r
347 xmlWriter.WriteEndElement();
\r
348 xmlWriter.WriteEndElement();
\r
350 xmlWriter.WriteEndDocument();
\r
356 private static void WritePreset(XmlTextWriter xmlWriter, QueryParser parsed)
\r
358 xmlWriter.WriteStartElement("dict");
\r
359 AudioListArrayDict(xmlWriter, parsed);
\r
360 AddEncodeSettings(xmlWriter, parsed);
\r
362 xmlWriter.WriteEndElement();
\r
365 private static void AddEncodeSettings(XmlTextWriter xmlWriter, QueryParser parsed)
\r
367 AddEncodeElement(xmlWriter, "ChapterMarkers", "integer", parsed.ChapterMarkers ? "1" : "0");
\r
368 AddEncodeElement(xmlWriter, "Default", "integer", string.Empty); // TODO
\r
369 AddEncodeElement(xmlWriter, "FileFormat", "string", parsed.Format);
\r
370 AddBooleanElement(xmlWriter, "Folder", true); // TODO
\r
371 AddEncodeElement(xmlWriter, "Mp4HttpOptimize", "integer", parsed.OptimizeMP4 ? "1" : "0");
\r
372 AddEncodeElement(xmlWriter, "Mp4LargeFile", "integer", parsed.LargeMP4 ? "1" : "0");
\r
373 AddEncodeElement(xmlWriter, "Mp4iPodCompatible", "integer", parsed.IpodAtom ? "1" : "0");
\r
374 AddEncodeElement(xmlWriter, "PictureAutoCrop", "integer", string.Empty); // TODO
\r
375 AddEncodeElement(xmlWriter, "PictureBottomCrop", "integer", parsed.CropBottom);
\r
377 // Filters - TODO Requires Some Logic to convert modes
\r
378 AddEncodeElement(xmlWriter, "PictureDeblock", "integer", string.Empty);
\r
379 AddEncodeElement(xmlWriter, "PictureDecomb", "integer", string.Empty);
\r
380 AddEncodeElement(xmlWriter, "PictureDecombCustom", "string", string.Empty);
\r
381 AddEncodeElement(xmlWriter, "PictureDecombDeinterlace", "integer", string.Empty); // TODO Requires Logic
\r
382 AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", string.Empty);
\r
383 AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", string.Empty);
\r
384 AddEncodeElement(xmlWriter, "PictureDenoise", "integer", string.Empty);
\r
385 AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", string.Empty);
\r
386 AddEncodeElement(xmlWriter, "PictureDetelecine", "integer", string.Empty);
\r
387 AddEncodeElement(xmlWriter, "PictureDetelecineCustom", "string", string.Empty);
\r
389 AddEncodeElement(xmlWriter, "PictureHeight", "integer", parsed.Height.ToString());
\r
390 AddEncodeElement(xmlWriter, "PictureKeepRatio", "integer", string.Empty);
\r
391 AddEncodeElement(xmlWriter, "PictureLeftCrop", "integer", parsed.CropLeft);
\r
392 AddEncodeElement(xmlWriter, "PicturePAR", "integer", string.Empty);
\r
393 AddEncodeElement(xmlWriter, "PictureRightCrop", "integer", parsed.CropRight);
\r
394 AddEncodeElement(xmlWriter, "PictureTopCrop", "integer", parsed.CropTop);
\r
395 AddEncodeElement(xmlWriter, "PictureWidth", "integer", parsed.Width.ToString());
\r
397 AddEncodeElement(xmlWriter, "PresetBuildNumber", "string", string.Empty);
\r
398 AddEncodeElement(xmlWriter, "PresetDescription", "string", string.Empty);
\r
399 AddEncodeElement(xmlWriter, "PresetName", "string", string.Empty);
\r
400 AddEncodeElement(xmlWriter, "Type", "integer", string.Empty);
\r
402 AddEncodeElement(xmlWriter, "UsesMaxPictureSettings", "integer", string.Empty);
\r
403 AddEncodeElement(xmlWriter, "UsesPictureFilters", "integer", string.Empty);
\r
404 AddEncodeElement(xmlWriter, "UsesPictureSettings", "integer", string.Empty);
\r
406 AddEncodeElement(xmlWriter, "VideoAvgBitrate", "string", string.Empty);
\r
407 AddEncodeElement(xmlWriter, "VideoEncoder", "string", string.Empty);
\r
408 AddEncodeElement(xmlWriter, "VideoFramerate", "string", string.Empty);
\r
410 AddEncodeElement(xmlWriter, "VideoGrayScale", "integer", parsed.Grayscale ? "1" : "0");
\r
411 AddEncodeElement(xmlWriter, "VideoQualitySlider", "real", parsed.VideoQuality.ToString());
\r
412 AddEncodeElement(xmlWriter, "VideoQualityType", "integer", string.Empty); // TODO Requires Logic
\r
413 AddEncodeElement(xmlWriter, "VideoTargetSize", "string", parsed.VideoTargetSize);
\r
414 AddEncodeElement(xmlWriter, "VideoTurboTwoPass", "integer", parsed.TurboFirstPass ? "1" : "0");
\r
415 AddEncodeElement(xmlWriter, "VideoTwoPass", "integer", parsed.TwoPass ? "1" : "0");
\r
417 AddEncodeElement(xmlWriter, "x264Option", "string", parsed.H264Query);
\r
420 private static void AddBooleanElement(XmlTextWriter xmlWriter, string keyName, bool value)
\r
422 xmlWriter.WriteStartElement("key");
\r
423 xmlWriter.WriteString(keyName);
\r
424 xmlWriter.WriteEndElement();
\r
427 xmlWriter.WriteStartElement("true");
\r
428 xmlWriter.WriteEndElement();
\r
432 xmlWriter.WriteStartElement("false");
\r
433 xmlWriter.WriteEndElement();
\r
437 private static void AddEncodeElement(XmlTextWriter xmlWriter, string keyName, string type, string value)
\r
439 xmlWriter.WriteElementString("key", keyName);
\r
440 xmlWriter.WriteElementString(type, value);
\r
443 private static void AudioListArrayDict(XmlTextWriter xmlWriter, QueryParser parsed)
\r
445 xmlWriter.WriteStartElement("key");
\r
446 xmlWriter.WriteString("AudioList");
\r
447 xmlWriter.WriteEndElement();
\r
449 xmlWriter.WriteStartElement("array");
\r
450 foreach (AudioTrack track in parsed.AudioInformation)
\r
452 AddAudioItem(xmlWriter, track);
\r
454 xmlWriter.WriteEndElement();
\r
457 private static void AddAudioItem(XmlTextWriter xmlWriter, AudioTrack audioTrack)
\r
459 string bitrate = audioTrack.Bitrate;
\r
460 string encoder = audioTrack.Encoder;
\r
461 string mixdown = audioTrack.MixDown;
\r
462 string sample = audioTrack.SampleRate;
\r
464 int.TryParse(audioTrack.Track, out track);
\r
465 string drc = audioTrack.DRC;
\r
466 string desc = "Automatic";
\r
468 xmlWriter.WriteStartElement("dict");
\r
470 xmlWriter.WriteElementString("key", "AudioBitrate");
\r
471 xmlWriter.WriteElementString("string", bitrate);
\r
473 xmlWriter.WriteElementString("key", "AudioEncoder");
\r
474 xmlWriter.WriteElementString("string", encoder);
\r
476 xmlWriter.WriteElementString("key", "AudioMixdown");
\r
477 xmlWriter.WriteElementString("string", mixdown);
\r
479 xmlWriter.WriteElementString("key", "AudioSamplerate");
\r
480 xmlWriter.WriteElementString("string", sample);
\r
482 xmlWriter.WriteElementString("key", "AudioTrack");
\r
483 xmlWriter.WriteElementString("integer", track.ToString());
\r
485 xmlWriter.WriteElementString("key", "AudioTrackDRCSlider");
\r
486 xmlWriter.WriteElementString("real", drc.ToString());
\r
488 xmlWriter.WriteElementString("key", "AudioTrackDescription");
\r
489 xmlWriter.WriteElementString("string", desc);
\r
491 xmlWriter.WriteEndElement();
\r