using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.IO; using System.Windows.Forms; using System.Text.RegularExpressions; namespace Handbrake.Parsing { /// /// An object that represents a single Title of a DVD /// public class Title { private List m_chapters; /// /// Collection of chapters in this Title /// public List Chapters { get { return this.m_chapters; } } private List m_audioTracks; /// /// Collection of audio tracks associated with this Title /// public List AudioTracks { get { return this.m_audioTracks; } } private List m_subtitles; /// /// Collection of subtitles associated with this Title /// public List Subtitles { get { return this.m_subtitles; } } private int m_titleNumber; /// /// The track number of this Title /// public int TitleNumber { get { return this.m_titleNumber; } } private TimeSpan m_duration; /// /// The length in time of this Title /// public TimeSpan Duration { get { return this.m_duration; } } private Size m_resolution; /// /// The resolution (width/height) of this Title /// public Size Resolution { get { return this.m_resolution; } } private float m_aspectRatio; /// /// The aspect ratio of this Title /// public float AspectRatio { get { return this.m_aspectRatio; } } private int[] m_autoCrop; /// /// The automatically detected crop region for this Title. /// This is an int array with 4 items in it as so: /// 0: /// 1: /// 2: /// 3: /// public int[] AutoCropDimensions { get { return this.m_autoCrop; } } /// /// The constructor for this object /// public Title() { this.m_audioTracks = new List(); this.m_chapters = new List(); this.m_subtitles = new List(); } /// /// Override of the ToString method to provide an easy way to use this object in the UI /// /// A string representing this track in the format: {title #} (00:00:00) public override string ToString() { return string.Format("{0} ({1:00}:{2:00}:{3:00})", this.m_titleNumber, this.m_duration.Hours, this.m_duration.Minutes, this.m_duration.Seconds); } public static Title Parse(StringReader output) { Title thisTitle = new Title(); // Match track number for this title Match m = Regex.Match(output.ReadLine(), @"^\+ title ([0-9]*):"); if (m.Success) { thisTitle.m_titleNumber = int.Parse(m.Groups[1].Value); } output.ReadLine(); /* // Match vts, ttn, cell range and block count m = Regex.Match(output.ReadLine(), @"^ \+ vts ([0-9]*), ttn ([0-9]*), cells ([0-9]*)->([0-9]*) \(([0-9]*) blocks\)"); if (m.Success) { // We don't need any of those values right now, so we'll just ignore them // and read a line from the buffer to get it out of the way. } */ // Get duration for this title m = Regex.Match(output.ReadLine(), @"^ \+ duration: ([0-9]{2}:[0-9]{2}:[0-9]{2})"); if (m.Success) { thisTitle.m_duration = TimeSpan.Parse(m.Groups[1].Value); } // Get resolution, aspect ratio and FPS for this title m = Regex.Match(output.ReadLine(), @"^ \+ size: ([0-9]*)x([0-9]*), aspect: ([0-9]*\.[0-9]*), ([0-9]*\.[0-9]*) fps"); if (m.Success) { thisTitle.m_resolution = new Size(int.Parse(m.Groups[1].Value), int.Parse(m.Groups[2].Value)); thisTitle.m_aspectRatio = float.Parse(m.Groups[3].Value); // we don't need FPS right now } // Get autocrop region for this title m = Regex.Match(output.ReadLine(), @"^ \+ autocrop: ([0-9]*)/([0-9]*)/([0-9]*)/([0-9]*)"); if (m.Success) { thisTitle.m_autoCrop = new int[4] { int.Parse(m.Groups[1].Value), int.Parse(m.Groups[2].Value), int.Parse(m.Groups[3].Value), int.Parse(m.Groups[4].Value) }; } /* * * A Few Bugs that need fixed. * * * Problem 1 * There is a small problem here... What happens if the DVD has no Subtitles? or Handbrake misses the Audio or Chapter track * data due to an error. * * hbcli will sit in a suspended state until it is forcefully closed. * * Problem 2 * See AudioTrack.cs Line 80 for details * * Problem 3 * Doesn't seem to support DVD's where the first track is 0 instead of 1, and only includes 1 title (TS/MPG files) * Simply Doesn't list any titles. * * */ thisTitle.m_chapters.AddRange(Chapter.ParseList(output)); thisTitle.m_audioTracks.AddRange(AudioTrack.ParseList(output)); thisTitle.m_subtitles.AddRange(Subtitle.ParseList(output)); return thisTitle; } public static Title[] ParseList(string output) { List titles = new List<Title>(); StringReader sr = new StringReader(output); while ((char)sr.Peek() == '+') { titles.Add(Title.Parse(sr)); } return titles.ToArray(); } } }