From b50f78e5da6f3fdfc59e577ca61b88771da7d211 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Thu, 12 Jul 2012 02:55:27 -0400 Subject: Initial check-in --- MediaBrowser.Controller/Xml/BaseItemXmlParser.cs | 591 +++++++++++++++++++++++ MediaBrowser.Controller/Xml/FolderXmlParser.cs | 8 + MediaBrowser.Controller/Xml/XmlExtensions.cs | 74 +++ 3 files changed, 673 insertions(+) create mode 100644 MediaBrowser.Controller/Xml/BaseItemXmlParser.cs create mode 100644 MediaBrowser.Controller/Xml/FolderXmlParser.cs create mode 100644 MediaBrowser.Controller/Xml/XmlExtensions.cs (limited to 'MediaBrowser.Controller/Xml') diff --git a/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs b/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs new file mode 100644 index 0000000000..2addf6a1d0 --- /dev/null +++ b/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs @@ -0,0 +1,591 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Xml +{ + public class BaseItemXmlParser + where T : BaseItem, new() + { + public virtual void Fetch(T item, string metadataFile) + { + XmlDocument doc = new XmlDocument(); + + doc.Load(metadataFile); + + XmlElement titleElement = doc.DocumentElement; + + foreach (XmlNode node in titleElement.ChildNodes) + { + FetchDataFromXmlNode(node, item); + } + + // If dates weren't supplied in metadata, use values from the file + if (item.DateCreated == DateTime.MinValue) + { + item.DateCreated = File.GetCreationTime(metadataFile); + } + + if (item.DateModified == DateTime.MinValue) + { + item.DateModified = File.GetLastWriteTime(metadataFile); + } + } + + protected virtual void FetchDataFromXmlNode(XmlNode node, T item) + { + switch (node.Name) + { + case "Added": + DateTime added; + if (DateTime.TryParse(node.InnerText ?? string.Empty, out added)) + { + item.DateCreated = added; + } + break; + + case "Type": + { + item.DisplayMediaType = node.InnerText ?? string.Empty; + + switch (item.DisplayMediaType.ToLower()) + { + case "blu-ray": + item.DisplayMediaType = VideoType.BluRay.ToString(); + break; + case "dvd": + item.DisplayMediaType = VideoType.DVD.ToString(); + break; + case "": + item.DisplayMediaType = null; + break; + } + + break; + } + + case "banner": + item.BannerImagePath = node.InnerText ?? string.Empty; + break; + + case "LocalTitle": + item.Name = node.InnerText ?? string.Empty; + break; + + case "SortTitle": + item.SortName = node.InnerText ?? string.Empty; + break; + + case "Overview": + case "Description": + item.Overview = node.InnerText ?? string.Empty; + break; + + case "TagLine": + item.Tagline = node.InnerText ?? string.Empty; + break; + + case "ContentRating": + case "MPAARating": + item.OfficialRating = node.InnerText ?? string.Empty; + break; + + case "CustomRating": + item.CustomRating = node.InnerText ?? string.Empty; + break; + + case "CustomPin": + item.CustomPin = node.InnerText ?? string.Empty; + break; + + case "Covers": + FetchFromCoversNode(node, item); + break; + + case "Genres": + FetchFromGenresNode(node, item); + break; + + case "Genre": + { + var genres = (item.Genres ?? new string[] { }).ToList(); + genres.AddRange(GetSplitValues(node.InnerText, '|')); + + item.Genres = genres; + break; + } + + case "AspectRatio": + item.AspectRatio = node.InnerText ?? string.Empty; + break; + + case "Rating": + case "IMDBrating": + float IMDBrating = node.SafeGetSingle((float)-1, (float)10); + + if (IMDBrating >= 0) + { + item.UserRating = IMDBrating; + } + break; + + case "Network": + { + var studios = (item.Studios ?? new string[] { }).ToList(); + studios.AddRange(GetSplitValues(node.InnerText, '|')); + + item.Studios = studios; + break; + } + case "Studios": + FetchFromStudiosNode(node, item); + break; + + case "Director": + { + var list = (item.People ?? new Person[]{}).ToList(); + list.AddRange(GetSplitValues(node.InnerText, '|').Select(v => new Person() { Name = v, PersonType = PersonType.Director })); + + item.People = list; + break; + } + case "Writer": + { + var list = (item.People ?? new Person[] { }).ToList(); + list.AddRange(GetSplitValues(node.InnerText, '|').Select(v => new Person() { Name = v, PersonType = PersonType.Writer })); + + item.People = list; + break; + } + + case "Actors": + case "GuestStars": + { + var list = (item.People ?? new Person[] { }).ToList(); + list.AddRange(GetSplitValues(node.InnerText, '|').Select(v => new Person() { Name = v, PersonType = PersonType.Actor })); + + item.People = list; + break; + } + + case "Persons": + FetchDataFromPersonsNode(node, item); + break; + + case "Trailer": + item.TrailerUrl = node.InnerText ?? string.Empty; + break; + + case "ParentalRating": + FetchFromParentalRatingNode(node, item); + break; + + case "ProductionYear": + { + int ProductionYear; + if (int.TryParse(node.InnerText, out ProductionYear) && ProductionYear > 1850) + { + item.ProductionYear = ProductionYear; + } + + break; + } + + case "MediaInfo": + FetchMediaInfo(node, item); + break; + + default: + break; + } + } + + protected virtual void FetchFromCoversNode(XmlNode node, T item) + { + string cover = node.SafeGetString("Front"); + + if (!string.IsNullOrEmpty(cover)) + { + item.PrimaryImagePath = cover; + } + } + + protected virtual void FetchMediaInfo(XmlNode node, T item) + { + var iMediaInfo = item as Video; + + if (iMediaInfo != null) + { + FetchMediaInfo(node, iMediaInfo); + } + } + + protected virtual void FetchMediaInfo(XmlNode node, Video item) + { + foreach (XmlNode childNode in node.ChildNodes) + { + switch (childNode.Name) + { + case "Audio": + { + AudioStream stream = FetchMediaInfoAudio(childNode); + + List streams = item.AudioStreams.ToList(); + streams.Add(stream); + item.AudioStreams = streams; + + break; + } + + case "Video": + FetchMediaInfoVideo(childNode, item); + break; + + case "Subtitle": + FetchMediaInfoSubtitles(childNode, item); + break; + + default: + break; + } + } + } + + protected virtual AudioStream FetchMediaInfoAudio(XmlNode node) + { + AudioStream stream = new AudioStream(); + + foreach (XmlNode childNode in node.ChildNodes) + { + switch (childNode.Name) + { + case "BitRate": + stream.BitRate = childNode.SafeGetInt32(); + break; + + case "Channels": + stream.Channels = childNode.SafeGetInt32(); + break; + + case "Language": + stream.Language = childNode.InnerText ?? string.Empty; + break; + + case "Codec": + { + string codec = childNode.InnerText ?? string.Empty; + + switch (codec.ToLower()) + { + case "dts-es": + case "dts-es matrix": + case "dts-es discrete": + stream.AudioFormat = "DTS"; + stream.AudioProfile = "ES"; + break; + case "dts-hd hra": + case "dts-hd high resolution": + stream.AudioFormat = "DTS"; + stream.AudioProfile = "HRA"; + break; + case "dts ma": + case "dts-hd ma": + case "dts-hd master": + stream.AudioFormat = "DTS"; + stream.AudioProfile = "MA"; + break; + case "dolby digital": + case "dolby digital surround ex": + case "dolby surround": + stream.AudioFormat = "AC-3"; + break; + case "dolby digital plus": + stream.AudioFormat = "E-AC-3"; + break; + case "dolby truehd": + stream.AudioFormat = "AC-3"; + stream.AudioProfile = "TrueHD"; + break; + case "mp2": + stream.AudioFormat = "MPEG Audio"; + stream.AudioProfile = "Layer 2"; + break; + case "other": + break; + default: + stream.AudioFormat = codec; + break; + } + + break; + } + + default: + break; + } + } + + return stream; + } + + protected virtual void FetchMediaInfoVideo(XmlNode node, Video item) + { + foreach (XmlNode childNode in node.ChildNodes) + { + switch (childNode.Name) + { + case "Width": + item.Width = childNode.SafeGetInt32(); + break; + + case "Height": + item.Height = childNode.SafeGetInt32(); + break; + + case "BitRate": + item.VideoBitRate = childNode.SafeGetInt32(); + break; + + case "FrameRate": + item.FrameRate = childNode.InnerText ?? string.Empty; + break; + + case "ScanType": + item.ScanType = childNode.InnerText ?? string.Empty; + break; + + case "Duration": + item.RunTime = TimeSpan.FromMinutes(childNode.SafeGetInt32()); + break; + + case "DurationSeconds": + int seconds = childNode.SafeGetInt32(); + if (seconds > 0) + { + item.RunTime = TimeSpan.FromSeconds(seconds); + } + break; + + case "Codec": + { + string videoCodec = childNode.InnerText ?? string.Empty; + + switch (videoCodec.ToLower()) + { + case "sorenson h.263": + item.VideoCodec = "Sorenson H263"; + break; + case "h.262": + item.VideoCodec = "MPEG-2 Video"; + break; + case "h.264": + item.VideoCodec = "AVC"; + break; + default: + item.VideoCodec = videoCodec; + break; + } + + break; + } + + default: + break; + } + } + } + + protected virtual void FetchMediaInfoSubtitles(XmlNode node, Video item) + { + List subtitles = item.Subtitles.ToList(); + + foreach (XmlNode childNode in node.ChildNodes) + { + switch (childNode.Name) + { + case "Language": + string lang = childNode.InnerText; + + if (!string.IsNullOrEmpty(lang)) + { + subtitles.Add(lang); + } + break; + + default: + break; + } + } + + item.Subtitles = subtitles; + } + + protected virtual void FetchFromGenresNode(XmlNode node, T item) + { + List list = (item.Genres ?? new string[] { }).ToList(); + + foreach (XmlNode childNode in node.ChildNodes) + { + switch (childNode.Name) + { + case "Genre": + string text = childNode.InnerText ?? string.Empty; + + if (!string.IsNullOrEmpty(text)) + { + list.Add(text); + } + break; + + default: + break; + } + + } + item.Genres = list; + } + + protected virtual void FetchDataFromPersonsNode(XmlNode node, T item) + { + List list = (item.People ?? new Person[] { }).ToList(); + + foreach (XmlNode childNode in node.ChildNodes) + { + switch (childNode.Name) + { + case "Person": + { + list.Add(GetPersonFromXmlNode(childNode)); + + break; + } + + default: + break; + } + + } + + item.People = list; + } + + protected virtual void FetchFromStudiosNode(XmlNode node, T item) + { + List list = (item.Studios ?? new string[] { }).ToList(); + + foreach (XmlNode childNode in node.ChildNodes) + { + switch (childNode.Name) + { + case "Studio": + string text = childNode.InnerText ?? string.Empty; + + if (!string.IsNullOrEmpty(text)) + { + list.Add(text); + } + break; + + default: + break; + } + } + + item.Studios = list; + } + + protected virtual void FetchFromParentalRatingNode(XmlNode node, T item) + { + foreach (XmlNode childNode in node.ChildNodes) + { + switch (childNode.Name) + { + case "Value": + { + int ParentalRating = childNode.SafeGetInt32((int)7); + + switch (ParentalRating) + { + case -1: + item.OfficialRating = "NR"; + break; + case 0: + item.OfficialRating = "UR"; + break; + case 1: + item.OfficialRating = "G"; + break; + case 3: + item.OfficialRating = "PG"; + break; + case 4: + item.OfficialRating = "PG-13"; + break; + case 5: + item.OfficialRating = "NC-17"; + break; + case 6: + item.OfficialRating = "R"; + break; + default: + break; + } + break; + } + + default: + break; + } + } + } + + private Person GetPersonFromXmlNode(XmlNode node) + { + Person person = new Person(); + + foreach (XmlNode childNode in node.ChildNodes) + { + switch (childNode.Name) + { + case "Name": + person.Name = childNode.InnerText ?? string.Empty; + break; + + case "Type": + { + string type = childNode.InnerText ?? string.Empty; + + if (type == "Director") + { + person.PersonType = PersonType.Director; + } + else if (type == "Actor") + { + person.PersonType = PersonType.Actor; + } + break; + } + + case "Role": + person.Description = childNode.InnerText ?? string.Empty; + break; + + default: + break; + } + + } + return person; + } + + protected IEnumerable GetSplitValues(string value, char deliminator) + { + value = (value ?? string.Empty).Trim(deliminator); + + return string.IsNullOrEmpty(value) ? new string[] { } : value.Split(deliminator); + } + } +} diff --git a/MediaBrowser.Controller/Xml/FolderXmlParser.cs b/MediaBrowser.Controller/Xml/FolderXmlParser.cs new file mode 100644 index 0000000000..d0dc7d4ec6 --- /dev/null +++ b/MediaBrowser.Controller/Xml/FolderXmlParser.cs @@ -0,0 +1,8 @@ +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Xml +{ + public class FolderXmlParser : BaseItemXmlParser + { + } +} diff --git a/MediaBrowser.Controller/Xml/XmlExtensions.cs b/MediaBrowser.Controller/Xml/XmlExtensions.cs new file mode 100644 index 0000000000..4f753a3f8a --- /dev/null +++ b/MediaBrowser.Controller/Xml/XmlExtensions.cs @@ -0,0 +1,74 @@ +using System; +using System.Globalization; +using System.Xml; + +namespace MediaBrowser.Controller.Xml +{ + public static class XmlExtensions + { + public static int SafeGetInt32(this XmlNode node) + { + return SafeGetInt32(node, 0); + } + + public static int SafeGetInt32(this XmlNode node, int defaultInt) + { + if (node != null && node.InnerText.Length > 0) + { + int rval; + if (Int32.TryParse(node.InnerText, out rval)) + { + return rval; + } + + } + return defaultInt; + } + + private static CultureInfo _usCulture = new CultureInfo("en-US"); + + public static float SafeGetSingle(this XmlNode rvalNode, float minValue, float maxValue) + { + if (rvalNode.InnerText.Length > 0) + { + float rval; + // float.TryParse is local aware, so it can be probamatic, force us culture + if (float.TryParse(rvalNode.InnerText, NumberStyles.AllowDecimalPoint, _usCulture, out rval)) + { + if (rval >= minValue && rval <= maxValue) + { + return rval; + } + } + + } + return minValue; + } + + public static float SafeGetSingle(this XmlNode doc, string path, float minValue, float maxValue) + { + XmlNode rvalNode = doc.SelectSingleNode(path); + if (rvalNode != null) + { + rvalNode.SafeGetSingle(minValue, maxValue); + + } + return minValue; + } + + + public static string SafeGetString(this XmlNode node) + { + return SafeGetString(node, null); + } + + public static string SafeGetString(this XmlNode node, string defaultValue) + { + if (node != null && node.InnerText.Length > 0) + { + return node.InnerText; + } + return defaultValue; + } + } +} -- cgit v1.2.3