-using System;\r
-using System.Collections.Generic;\r
-using System.Text;\r
-using System.Drawing;\r
-using System.IO;\r
+/* Title.cs $\r
+ This file is part of the HandBrake source code.\r
+ Homepage: <http://handbrake.fr>.\r
+ It may be used under the terms of the GNU General Public License. */\r
\r
namespace Handbrake.Parsing\r
{\r
+ using System;\r
+ using System.Collections.Generic;\r
+ using System.Drawing;\r
+ using System.Globalization;\r
+ using System.IO;\r
+ using System.Text.RegularExpressions;\r
+\r
+ /// <summary>\r
+ /// An object that represents a single Title of a DVD\r
+ /// </summary>\r
public class Title\r
{\r
- private List<Chapter> m_chapters;\r
+ /// <summary>\r
+ /// The Culture Info\r
+ /// </summary>\r
+ private static readonly CultureInfo Culture = new CultureInfo("en-US", false);\r
+\r
+ /// <summary>\r
+ /// A collection of Audio Tracks\r
+ /// </summary>\r
+ private readonly List<AudioTrack> audioTracks;\r
+\r
+ /// <summary>\r
+ /// A Collection of Chapters\r
+ /// </summary>\r
+ private readonly List<Chapter> chapters;\r
+\r
+ /// <summary>\r
+ /// A Collection of Subtitles\r
+ /// </summary>\r
+ private readonly List<Subtitle> subtitles;\r
+\r
+ /// <summary>\r
+ /// A collection of angles \r
+ /// </summary>\r
+ private List<string> angles = new List<string>();\r
+\r
+ /// <summary>\r
+ /// The source aspect ratio\r
+ /// </summary>\r
+ private float aspectRatio;\r
+\r
+ /// <summary>\r
+ /// The source framerate\r
+ /// </summary>\r
+ private float fps;\r
+\r
+ /// <summary>\r
+ /// Source autocrop values\r
+ /// </summary>\r
+ private int[] autoCrop;\r
+\r
+ /// <summary>\r
+ /// Source name\r
+ /// </summary>\r
+ private string source;\r
+\r
+ /// <summary>\r
+ /// The duration of the source\r
+ /// </summary>\r
+ private TimeSpan duration;\r
+\r
+ /// <summary>\r
+ /// The source resolution\r
+ /// </summary>\r
+ private Size resolution;\r
+\r
+ /// <summary>\r
+ /// The Title number\r
+ /// </summary>\r
+ private int titleNumber;\r
+\r
+ /// <summary>\r
+ /// The par values for this title.\r
+ /// </summary>\r
+ private Size parVal;\r
+\r
+ /// <summary>\r
+ /// Initializes a new instance of the <see cref="Title"/> class. \r
+ /// The constructor for this object\r
+ /// </summary>\r
+ public Title()\r
+ {\r
+ audioTracks = new List<AudioTrack>();\r
+ chapters = new List<Chapter>();\r
+ subtitles = new List<Subtitle>();\r
+ }\r
+\r
+ /// <summary>\r
+ /// Gets a Collection of chapters in this Title\r
+ /// </summary>\r
public List<Chapter> Chapters\r
{\r
- get\r
- {\r
- return this.m_chapters;\r
- }\r
+ get { return chapters; }\r
}\r
\r
- private List<AudioTrack> m_audioTracks;\r
+ /// <summary>\r
+ /// Gets a Collection of audio tracks associated with this Title\r
+ /// </summary>\r
public List<AudioTrack> AudioTracks\r
{\r
- get\r
- {\r
- return this.m_audioTracks;\r
- }\r
+ get { return audioTracks; }\r
}\r
\r
- private List<Subtitle> m_subtitles;\r
+ /// <summary>\r
+ /// Gets aCollection of subtitles associated with this Title\r
+ /// </summary>\r
public List<Subtitle> Subtitles\r
{\r
- get\r
- {\r
- return this.m_subtitles;\r
- }\r
+ get { return subtitles; }\r
}\r
\r
- private int m_vts;\r
- public int Vts\r
+ /// <summary>\r
+ /// The track number of this Title\r
+ /// </summary>\r
+ public int TitleNumber\r
{\r
- get\r
- {\r
- return this.m_vts;\r
- }\r
+ get { return titleNumber; }\r
}\r
\r
- private int m_ttn;\r
- public int Ttn\r
+ /// <summary>\r
+ /// Gets the Source Name\r
+ /// </summary>\r
+ public string SourceName\r
{\r
- get\r
- {\r
- return this.m_ttn;\r
- }\r
+ get { return source; }\r
}\r
\r
- private int[] m_cellRange;\r
- public int[] CellRange\r
+ /// <summary>\r
+ /// Gets the length in time of this Title\r
+ /// </summary>\r
+ public TimeSpan Duration\r
{\r
- get\r
- {\r
- return this.m_cellRange;\r
- }\r
+ get { return duration; }\r
}\r
\r
- private int m_blockCount;\r
- public int BlockCount\r
+ /// <summary>\r
+ /// Gets the resolution (width/height) of this Title\r
+ /// </summary>\r
+ public Size Resolution\r
{\r
- get\r
- {\r
- return this.m_blockCount;\r
- }\r
+ get { return resolution; }\r
}\r
\r
- private int m_titleNumber;\r
- public int TitleNumber\r
+ /// <summary>\r
+ /// Gets the aspect ratio of this Title\r
+ /// </summary>\r
+ public float AspectRatio\r
{\r
- get\r
- {\r
- return this.m_titleNumber;\r
- }\r
+ get { return aspectRatio; }\r
}\r
\r
- private TimeSpan m_duration;\r
- public TimeSpan Duration\r
+ /// <summary>\r
+ /// Gets Par Value\r
+ /// </summary>\r
+ public Size ParVal\r
{\r
- get\r
- {\r
- return this.m_duration;\r
- }\r
+ get { return parVal; }\r
}\r
\r
- private Size m_resolution;\r
- public Size Resolution\r
+ /// <summary>\r
+ /// Gets the automatically detected crop region for this Title.\r
+ /// This is an int array with 4 items in it as so:\r
+ /// 0: \r
+ /// 1: \r
+ /// 2: \r
+ /// 3: \r
+ /// </summary>\r
+ public int[] AutoCropDimensions\r
{\r
- get\r
- {\r
- return this.m_resolution;\r
- }\r
+ get { return autoCrop; }\r
}\r
\r
- private float m_aspectRatio;\r
- public float AspectRatio\r
+ /// <summary>\r
+ /// Gets a Collection of Angles in this Title\r
+ /// </summary>\r
+ public List<string> Angles\r
{\r
- get\r
- {\r
- return this.m_aspectRatio;\r
- }\r
+ get { return angles; }\r
}\r
\r
- private float m_fps;\r
+\r
+ /// <summary>\r
+ /// Gets the FPS of the source.\r
+ /// </summary>\r
public float Fps\r
{\r
- get\r
- {\r
- return this.m_fps;\r
- }\r
+ get { return fps; }\r
}\r
\r
- private int[] m_autoCrop;\r
- public int[] AutoCropDimensions\r
+ /// <summary>\r
+ /// Override of the ToString method to provide an easy way to use this object in the UI\r
+ /// </summary>\r
+ /// <returns>A string representing this track in the format: {title #} (00:00:00)</returns>\r
+ public override string ToString()\r
{\r
- get\r
- {\r
- return this.m_autoCrop;\r
- }\r
+ return string.Format("{0} ({1:00}:{2:00}:{3:00})", titleNumber, duration.Hours, duration.Minutes, duration.Seconds);\r
}\r
\r
- public Title()\r
+ /// <summary>\r
+ /// Parse the Title Information\r
+ /// </summary>\r
+ /// <param name="output">A stingreader of output data</param>\r
+ /// <returns>A Title</returns>\r
+ public static Title Parse(StringReader output)\r
{\r
- this.m_audioTracks = new List<AudioTrack>();\r
- this.m_chapters = new List<Chapter>();\r
- this.m_subtitles = new List<Subtitle>();\r
- this.m_cellRange = new int[2];\r
- }\r
+ var thisTitle = new Title();\r
\r
- public override string ToString()\r
- {\r
- return string.Format("{0} - {1}h{2}m{3}s", this.m_titleNumber, this.m_duration.Hours, \r
- this.m_duration.Minutes, this.m_duration.Seconds);\r
- }\r
-\r
- public static Title Parse(StreamReader output)\r
- {\r
- Title thisTitle = new Title();\r
-\r
- /*\r
- * This will be converted to use Regex soon, I promise ;)\r
- * brianmario - 7/9/07\r
- */\r
-\r
- string curLine = output.ReadLine();\r
- thisTitle.m_titleNumber = int.Parse(curLine.Substring(curLine.Length - 2, 1));\r
- curLine = output.ReadLine();\r
- string[] splitter = curLine.Split(',');\r
- thisTitle.m_vts = int.Parse(splitter[0].Substring(8));\r
- thisTitle.m_ttn = int.Parse(splitter[1].Substring(5));\r
- splitter = splitter[2].Trim().Split(' ', '(', ')');\r
- thisTitle.m_blockCount = int.Parse(splitter[3]);\r
- splitter = splitter[1].Split('-', '>');\r
- thisTitle.m_cellRange[0] = int.Parse(splitter[0]);\r
- thisTitle.m_cellRange[1] = int.Parse(splitter[2]);\r
- curLine = output.ReadLine();\r
- splitter = curLine.Split(new string[] { " + duration: " }, StringSplitOptions.RemoveEmptyEntries);\r
- thisTitle.m_duration = TimeSpan.Parse(splitter[0]);\r
- curLine = output.ReadLine();\r
- splitter = curLine.Split(new string[] { " + size: ", "aspect: ", ", ", " fps", "x" }, StringSplitOptions.RemoveEmptyEntries);\r
- thisTitle.m_resolution = new Size(int.Parse(splitter[0]), int.Parse(splitter[1]));\r
- thisTitle.m_aspectRatio = float.Parse(splitter[2].ToString());\r
- thisTitle.m_fps = float.Parse(splitter[3].ToString());\r
- curLine = output.ReadLine();\r
- splitter = curLine.Split(new string[] { " + autocrop: ", "/" }, StringSplitOptions.RemoveEmptyEntries);\r
- thisTitle.m_autoCrop = new int[4] { int.Parse(splitter[0]), int.Parse(splitter[1]), int.Parse(splitter[2]), int.Parse(splitter[3]) };\r
- thisTitle.m_chapters.AddRange(Chapter.ParseList(output));\r
- thisTitle.m_audioTracks.AddRange(AudioTrack.ParseList(output));\r
- thisTitle.m_subtitles.AddRange(Subtitle.ParseList(output));\r
+ Match m = Regex.Match(output.ReadLine(), @"^\+ title ([0-9]*):");\r
+ // Match track number for this title\r
+ if (m.Success)\r
+ thisTitle.titleNumber = int.Parse(m.Groups[1].Value.Trim());\r
+\r
+ // If we are scanning a groupd of files, we'll want to get the source name.\r
+ string path = output.ReadLine();\r
+ m = Regex.Match(path, @"^ \+ stream:");\r
+ if (m.Success)\r
+ thisTitle.source = path.Replace("+ stream:", string.Empty).Trim();\r
+\r
+ if (!Properties.Settings.Default.noDvdNav)\r
+ {\r
+ // Get the Angles for the title.\r
+ m = Regex.Match(output.ReadLine(), @" \+ angle\(s\) ([0-9])");\r
+ if (m.Success)\r
+ {\r
+ string angleList = m.Value.Replace("+ angle(s) ", string.Empty).Trim();\r
+ int angleCount;\r
+ int.TryParse(angleList, out angleCount);\r
+\r
+ for (int i = 1; i <= angleCount; i++)\r
+ thisTitle.angles.Add(i.ToString());\r
+ }\r
+ }\r
+\r
+ // Get duration for this title\r
+ m = Regex.Match(output.ReadLine(), @"^ \+ duration: ([0-9]{2}:[0-9]{2}:[0-9]{2})");\r
+ if (m.Success)\r
+ thisTitle.duration = TimeSpan.Parse(m.Groups[1].Value);\r
+\r
+ // Get resolution, aspect ratio and FPS for this title\r
+ m = Regex.Match(output.ReadLine(), @"^ \+ size: ([0-9]*)x([0-9]*), pixel aspect: ([0-9]*)/([0-9]*), display aspect: ([0-9]*\.[0-9]*), ([0-9]*\.[0-9]*) fps");\r
+ if (m.Success)\r
+ {\r
+ thisTitle.resolution = new Size(int.Parse(m.Groups[1].Value), int.Parse(m.Groups[2].Value));\r
+ thisTitle.parVal = new Size(int.Parse(m.Groups[3].Value), int.Parse(m.Groups[4].Value));\r
+ thisTitle.aspectRatio = float.Parse(m.Groups[5].Value, Culture);\r
+ thisTitle.fps = float.Parse(m.Groups[6].Value, Culture);\r
+ }\r
+\r
+ // Get autocrop region for this title\r
+ m = Regex.Match(output.ReadLine(), @"^ \+ autocrop: ([0-9]*)/([0-9]*)/([0-9]*)/([0-9]*)");\r
+ if (m.Success)\r
+ thisTitle.autoCrop = new[]\r
+ {\r
+ int.Parse(m.Groups[1].Value), int.Parse(m.Groups[2].Value), \r
+ int.Parse(m.Groups[3].Value), int.Parse(m.Groups[4].Value)\r
+ };\r
+\r
+ thisTitle.chapters.AddRange(Chapter.ParseList(output));\r
+\r
+ thisTitle.audioTracks.AddRange(AudioTrack.ParseList(output));\r
+\r
+ thisTitle.subtitles.AddRange(Subtitle.ParseList(output));\r
\r
return thisTitle;\r
}\r
\r
- public static Title[] ParseList(StreamReader output)\r
+ /// <summary>\r
+ /// Return a list of parsed titles\r
+ /// </summary>\r
+ /// <param name="output">The Output</param>\r
+ /// <returns>A List of titles</returns>\r
+ public static Title[] ParseList(string output)\r
{\r
- List<Title> titles = new List<Title>();\r
- while ((char)output.Peek() == '+')\r
+ var titles = new List<Title>();\r
+ var sr = new StringReader(output);\r
+\r
+ while (sr.Peek() == '+' || sr.Peek() == ' ')\r
{\r
- titles.Add(Title.Parse(output));\r
+ // If the the character is a space, then chances are the line\r
+ if (sr.Peek() == ' ') // If the character is a space, then chances are it's the combing detected line.\r
+ sr.ReadLine(); // Skip over it\r
+ else\r
+ titles.Add(Parse(sr));\r
}\r
+\r
return titles.ToArray();\r
}\r
}\r
-}\r
+}
\ No newline at end of file