diff options
author | Scott <[email protected]> | 2015-09-26 20:58:05 +0100 |
---|---|---|
committer | Scott <[email protected]> | 2015-09-26 21:30:31 +0100 |
commit | e703a7961f12a3e02c475754862a1f4a57a04646 (patch) | |
tree | bc0a611446ab624082b27ebcc22980f250a05838 /win/CS/HandBrakeWPF/Services/Scan | |
parent | efcddfdf4fc67f59bf09154a0c8d2d20ba61c895 (diff) |
AppServices tidyup
Moving the UI modelling and services to the GUI Project.
Diffstat (limited to 'win/CS/HandBrakeWPF/Services/Scan')
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Scan/EventArgs/ScanCompletedEventArgs.cs | 70 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Scan/EventArgs/ScanProgressEventArgs.cs | 39 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Scan/Interfaces/IScan.cs | 113 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Scan/LibScan.cs | 600 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Scan/Model/Audio.cs | 181 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Scan/Model/Chapter.cs | 70 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Scan/Model/Source.cs | 57 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Scan/Model/Subtitle.cs | 207 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Scan/Model/Title.cs | 159 |
9 files changed, 1496 insertions, 0 deletions
diff --git a/win/CS/HandBrakeWPF/Services/Scan/EventArgs/ScanCompletedEventArgs.cs b/win/CS/HandBrakeWPF/Services/Scan/EventArgs/ScanCompletedEventArgs.cs new file mode 100644 index 000000000..75520fef6 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Scan/EventArgs/ScanCompletedEventArgs.cs @@ -0,0 +1,70 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="ScanCompletedEventArgs.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Scan Progress Event Args +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Scan.EventArgs +{ + using System; + + using HandBrakeWPF.Services.Scan.Model; + + /// <summary> + /// Scan Progress Event Args + /// </summary> + public class ScanCompletedEventArgs : EventArgs + { + /// <summary> + /// Initializes a new instance of the <see cref="ScanCompletedEventArgs"/> class. + /// </summary> + /// <param name="cancelled"> + /// Whether the scan was cancelled. + /// </param> + /// <param name="exception"> + /// The exception. + /// </param> + /// <param name="errorInformation"> + /// The error information. + /// </param> + /// <param name="scannedSource"> + /// The scanned Source. + /// </param> + public ScanCompletedEventArgs(bool cancelled, Exception exception, string errorInformation, Source scannedSource) + { + this.Successful = !cancelled && exception == null && string.IsNullOrEmpty(errorInformation) && scannedSource != null && scannedSource.Titles != null && scannedSource.Titles.Count > 0; + this.Cancelled = cancelled; + this.Exception = exception; + this.ErrorInformation = errorInformation; + this.ScannedSource = scannedSource; + } + + /// <summary> + /// Gets a value indicating whether Successful. + /// </summary> + public bool Successful { get; private set; } + + /// <summary> + /// Gets a value indicating whether Cancelled. + /// </summary> + public bool Cancelled { get; private set; } + + /// <summary> + /// Gets the Exception. + /// </summary> + public Exception Exception { get; private set; } + + /// <summary> + /// Gets ErrorInformation. + /// </summary> + public string ErrorInformation { get; private set; } + + /// <summary> + /// Gets the scanned source. + /// </summary> + public Source ScannedSource { get; private set; } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Scan/EventArgs/ScanProgressEventArgs.cs b/win/CS/HandBrakeWPF/Services/Scan/EventArgs/ScanProgressEventArgs.cs new file mode 100644 index 000000000..8d815b746 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Scan/EventArgs/ScanProgressEventArgs.cs @@ -0,0 +1,39 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="ScanProgressEventArgs.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Scan Progress Event Args +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Scan.EventArgs +{ + using System; + using System.Runtime.Serialization; + + /// <summary> + /// Scan Progress Event Args + /// </summary> + [DataContract] + public class ScanProgressEventArgs : EventArgs + { + /// <summary> + /// Gets or sets the title currently being scanned. + /// </summary> + [DataMember] + public int CurrentTitle { get; set; } + + /// <summary> + /// Gets or sets the total number of Titles. + /// </summary> + [DataMember] + public int Titles { get; set; } + + /// <summary> + /// Gets or sets the percentage. + /// </summary> + [DataMember] + public decimal Percentage { get; set; } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Scan/Interfaces/IScan.cs b/win/CS/HandBrakeWPF/Services/Scan/Interfaces/IScan.cs new file mode 100644 index 000000000..1c0d3a851 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Scan/Interfaces/IScan.cs @@ -0,0 +1,113 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="IScan.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Encode Progess Status +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Scan.Interfaces +{ + using System; + using System.Windows.Media.Imaging; + + using HandBrake.ApplicationServices.Model; + + using HandBrakeWPF.Services.Encode.Model; + using HandBrakeWPF.Services.Scan.EventArgs; + using HandBrakeWPF.Services.Scan.Model; + + /// <summary> + /// Encode Progess Status + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The EncodeProgressEventArgs. + /// </param> + public delegate void ScanProgessStatus(object sender, ScanProgressEventArgs e); + + /// <summary> + /// Encode Progess Status + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The ScanCompletedEventArgs. + /// </param> + public delegate void ScanCompletedStatus(object sender, ScanCompletedEventArgs e); + + /// <summary> + /// The IScan Interface + /// </summary> + public interface IScan + { + /// <summary> + /// Scan has Started + /// </summary> + event EventHandler ScanStarted; + + /// <summary> + /// Scan has completed + /// </summary> + event ScanCompletedStatus ScanCompleted; + + /// <summary> + /// Scan process has changed to a new title + /// </summary> + event ScanProgessStatus ScanStatusChanged; + + /// <summary> + /// Gets a value indicating whether IsScanning. + /// </summary> + bool IsScanning { get; } + + /// <summary> + /// Gets ActivityLog. + /// </summary> + string ActivityLog { get; } + + /// <summary> + /// Scan a Source Path. + /// Title 0: scan all + /// </summary> + /// <param name="sourcePath"> + /// Path to the file to scan + /// </param> + /// <param name="title"> + /// int title number. 0 for scan all + /// </param> + /// <param name="postAction"> + /// The post Action. + /// </param> + /// <param name="configuration"> + /// The configuraiton. + /// </param> + void Scan(string sourcePath, int title, Action<bool, Source> postAction, HBConfiguration configuration); + + /// <summary> + /// Get a Preview image for the current job and preview number. + /// </summary> + /// <param name="task"> + /// The task. + /// </param> + /// <param name="preview"> + /// The preview. + /// </param> + /// <param name="configuration"> + /// The configuration. + /// </param> + /// <returns> + /// The <see cref="BitmapImage"/>. + /// </returns> + BitmapImage GetPreview(EncodeTask task, int preview, HBConfiguration configuration); + + /// <summary> + /// Kill the scan + /// </summary> + void Stop(); + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Scan/LibScan.cs b/win/CS/HandBrakeWPF/Services/Scan/LibScan.cs new file mode 100644 index 000000000..2aae331d6 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Scan/LibScan.cs @@ -0,0 +1,600 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="LibScan.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Scan a Source +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Scan +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.IO; + using System.Text; + using System.Windows.Media.Imaging; + + using HandBrake.ApplicationServices.Interop; + using HandBrake.ApplicationServices.Interop.EventArgs; + using HandBrake.ApplicationServices.Interop.HbLib; + using HandBrake.ApplicationServices.Interop.Interfaces; + using HandBrake.ApplicationServices.Interop.Json.Scan; + using HandBrake.ApplicationServices.Interop.Model; + using HandBrake.ApplicationServices.Interop.Model.Preview; + using HandBrake.ApplicationServices.Model; + using HandBrake.ApplicationServices.Utilities; + + using HandBrakeWPF.Services.Encode.Model; + using HandBrakeWPF.Services.Encode.Model.Models; + using HandBrakeWPF.Services.Scan.EventArgs; + using HandBrakeWPF.Services.Scan.Interfaces; + using HandBrakeWPF.Services.Scan.Model; + + using Chapter = HandBrakeWPF.Services.Scan.Model.Chapter; + using ScanProgressEventArgs = HandBrake.ApplicationServices.Interop.EventArgs.ScanProgressEventArgs; + using Subtitle = HandBrakeWPF.Services.Scan.Model.Subtitle; + using Title = HandBrakeWPF.Services.Scan.Model.Title; + + /// <summary> + /// Scan a Source + /// </summary> + public class LibScan : IScan + { + #region Private Variables + + /// <summary> + /// Lock for the log file + /// </summary> + static readonly object LogLock = new object(); + + /// <summary> + /// Log data from HandBrakeInstance + /// </summary> + private readonly StringBuilder logging; + + /// <summary> + /// The Log File Header + /// </summary> + private readonly StringBuilder header; + + /// <summary> + /// The Current source scan path. + /// </summary> + private string currentSourceScanPath; + + /// <summary> + /// The log dir. + /// </summary> + private static string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs"; + + /// <summary> + /// The dvd info path. + /// </summary> + private string dvdInfoPath = Path.Combine(logDir, string.Format("last_scan_log{0}.txt", GeneralUtilities.ProcessId)); + + /// <summary> + /// The scan log. + /// </summary> + private StreamWriter scanLog; + + /// <summary> + /// LibHB Instance + /// </summary> + private IHandBrakeInstance instance; + + /// <summary> + /// The post scan operation. + /// </summary> + private Action<bool, Source> postScanOperation; + + #endregion + + /// <summary> + /// Initializes a new instance of the <see cref="LibScan"/> class. + /// </summary> + public LibScan() + { + this.logging = new StringBuilder(); + this.header = GeneralUtilities.CreateLogHeader(); + this.IsScanning = false; + } + + #region Events + + /// <summary> + /// Scan has Started + /// </summary> + public event EventHandler ScanStarted; + + /// <summary> + /// Scan has completed + /// </summary> + public event ScanCompletedStatus ScanCompleted; + + /// <summary> + /// Encode process has progressed + /// </summary> + public event ScanProgessStatus ScanStatusChanged; + + #endregion + + #region Properties + + /// <summary> + /// Gets a value indicating whether IsScanning. + /// </summary> + public bool IsScanning { get; private set; } + + /// <summary> + /// Gets ActivityLog. + /// </summary> + public string ActivityLog + { + get + { + string noLog = "There is no log information to display." + Environment.NewLine + Environment.NewLine + + "This window will only display logging information after you have scanned a source." + Environment.NewLine + + Environment.NewLine + "You can find previous log files in the log directory or by clicking the 'Open Log Directory' button above."; + + return string.IsNullOrEmpty(this.logging.ToString()) ? noLog : this.header + this.logging.ToString(); + } + } + + #endregion + + #region Public Methods + + /// <summary> + /// Scan a Source Path. + /// Title 0: scan all + /// </summary> + /// <param name="sourcePath"> + /// Path to the file to scan + /// </param> + /// <param name="title"> + /// int title number. 0 for scan all + /// </param> + /// <param name="postAction"> + /// The post Action. + /// </param> + /// <param name="configuraiton"> + /// The configuraiton. + /// </param> + public void Scan(string sourcePath, int title, Action<bool, Source> postAction, HBConfiguration configuraiton) + { + // Try to cleanup any previous scan instances. + if (this.instance != null) + { + try + { + lock (LogLock) + { + this.scanLog.Close(); + this.scanLog.Dispose(); + this.scanLog = null; + } + this.instance.Dispose(); + } + catch (Exception) + { + // Do Nothing + } + } + + // Handle the post scan operation. + this.postScanOperation = postAction; + + // Clear down the logging + this.logging.Clear(); + + try + { + // Make we don't pick up a stale last_scan_log_xyz.txt (and that we have rights to the file) + if (File.Exists(this.dvdInfoPath)) + { + File.Delete(this.dvdInfoPath); + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); + } + + if (!Directory.Exists(Path.GetDirectoryName(this.dvdInfoPath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(this.dvdInfoPath)); + } + + // Create a new scan log. + this.scanLog = new StreamWriter(this.dvdInfoPath); + + // Create a new HandBrake Instance. + HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged; + HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged; + this.instance = HandBrakeInstanceManager.GetScanInstance(configuraiton.Verbosity); + this.instance.ScanProgress += this.InstanceScanProgress; + this.instance.ScanCompleted += this.InstanceScanCompleted; + + // Start the scan on a back + this.ScanSource(sourcePath, title, configuraiton.PreviewScanCount, configuraiton); + } + + /// <summary> + /// Kill the scan + /// </summary> + public void Stop() + { + try + { + this.ServiceLogMessage("Stopping Scan."); + this.IsScanning = false; + this.instance.StopScan(); + + lock (LogLock) + { + if (this.scanLog != null) + { + this.scanLog.Close(); + this.scanLog.Dispose(); + this.scanLog = null; + } + } + } + catch (Exception) + { + // Do Nothing. + } + } + + /// <summary> + /// Get a Preview image for the current job and preview number. + /// </summary> + /// <param name="job"> + /// The job. + /// </param> + /// <param name="preview"> + /// The preview. + /// </param> + /// <param name="configuraiton"> + /// The configuraiton. + /// </param> + /// <returns> + /// The <see cref="BitmapImage"/>. + /// </returns> + public BitmapImage GetPreview(EncodeTask job, int preview, HBConfiguration configuraiton) + { + if (this.instance == null) + { + return null; + } + + BitmapImage bitmapImage = null; + try + { + PreviewSettings settings = new PreviewSettings + { + Cropping = new Cropping(job.Cropping), + MaxWidth = job.MaxWidth ?? 0, + MaxHeight = job.MaxHeight ?? 0, + KeepDisplayAspect = job.KeepDisplayAspect, + TitleNumber = job.Title, + Anamorphic = job.Anamorphic, + Modulus = job.Modulus, + Width = job.Width ?? 0, + Height = job.Height ?? 0, + PixelAspectX = job.PixelAspectX, + PixelAspectY = job.PixelAspectY + }; + + bitmapImage = this.instance.GetPreview(settings, preview); + } + catch (AccessViolationException e) + { + Console.WriteLine(e); + } + + return bitmapImage; + } + + #endregion + + #region Private Methods + + /// <summary> + /// Start a scan for a given source path and title + /// </summary> + /// <param name="sourcePath"> + /// Path to the source file + /// </param> + /// <param name="title"> + /// the title number to look at + /// </param> + /// <param name="previewCount"> + /// The preview Count. + /// </param> + /// <param name="configuraiton"> + /// The configuraiton. + /// </param> + private void ScanSource(object sourcePath, int title, int previewCount, HBConfiguration configuraiton) + { + try + { + this.logging.Clear(); + + string source = sourcePath.ToString().EndsWith("\\") ? string.Format("\"{0}\\\\\"", sourcePath.ToString().TrimEnd('\\')) + : "\"" + sourcePath + "\""; + this.currentSourceScanPath = source; + + this.IsScanning = true; + + TimeSpan minDuration = TimeSpan.FromSeconds(configuraiton.MinScanDuration); + + HandBrakeUtils.SetDvdNav(!configuraiton.IsDvdNavDisabled); + + this.ServiceLogMessage("Starting Scan ..."); + this.instance.StartScan(sourcePath.ToString(), previewCount, minDuration, title != 0 ? title : 0); + + if (this.ScanStarted != null) + this.ScanStarted(this, System.EventArgs.Empty); + } + catch (Exception exc) + { + this.ServiceLogMessage("Scan Failed ..." + Environment.NewLine + exc); + this.Stop(); + + if (this.ScanCompleted != null) + this.ScanCompleted(this, new ScanCompletedEventArgs(false, exc, "An Error has occured in ScanService.ScanSource()", null)); + } + } + + #endregion + + #region HandBrakeInstance Event Handlers + /// <summary> + /// Scan Completed Event Handler + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The EventArgs. + /// </param> + private void InstanceScanCompleted(object sender, System.EventArgs e) + { + this.ServiceLogMessage("Scan Finished ..."); + + // Write the log file out before we start processing incase we crash. + try + { + if (this.scanLog != null) + { + this.scanLog.Flush(); + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); + } + + HandBrakeUtils.MessageLogged -= this.HandBrakeInstanceMessageLogged; + HandBrakeUtils.ErrorLogged -= this.HandBrakeInstanceErrorLogged; + + // TODO -> Might be a better place to fix this. + string path = this.currentSourceScanPath; + if (this.currentSourceScanPath.Contains("\"")) + { + path = this.currentSourceScanPath.Trim('\"'); + } + + // Process into internal structures. + Source sourceData = null; + if (this.instance != null && this.instance.Titles != null) + { + sourceData = new Source { Titles = ConvertTitles(this.instance.Titles), ScanPath = path }; + } + + this.IsScanning = false; + + if (this.postScanOperation != null) + { + try + { + this.postScanOperation(true, sourceData); + } + catch (Exception exc) + { + Debug.WriteLine(exc); + } + + this.postScanOperation = null; // Reset + } + else + { + if (this.ScanCompleted != null) this.ScanCompleted(this, new ScanCompletedEventArgs(false, null, string.Empty, sourceData)); + } + } + + /// <summary> + /// Scan Progress Event Handler + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The EventArgs. + /// </param> + private void InstanceScanProgress(object sender, ScanProgressEventArgs e) + { + if (this.ScanStatusChanged != null) + { + HandBrakeWPF.Services.Scan.EventArgs.ScanProgressEventArgs eventArgs = + new HandBrakeWPF.Services.Scan.EventArgs.ScanProgressEventArgs + { + CurrentTitle = e.CurrentTitle, + Titles = e.Titles, + Percentage = Math.Round((decimal)e.Progress * 100, 0) + }; + + this.ScanStatusChanged(this, eventArgs); + } + } + + /// <summary> + /// Log a message + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The MessageLoggedEventArgs. + /// </param> + private void HandBrakeInstanceErrorLogged(object sender, MessageLoggedEventArgs e) + { + this.LogMessage(e.Message); + } + + /// <summary> + /// Log a message + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The MessageLoggedEventArgs. + /// </param> + private void HandBrakeInstanceMessageLogged(object sender, MessageLoggedEventArgs e) + { + this.LogMessage(e.Message); + } + + /// <summary> + /// Convert Interop Title objects to App Services Title object + /// </summary> + /// <param name="titles"> + /// The titles. + /// </param> + /// <returns> + /// The convert titles. + /// </returns> + internal static List<Title> ConvertTitles(JsonScanObject titles) + { + List<Title> titleList = new List<Title>(); + foreach (SourceTitle title in titles.TitleList) + { + Title converted = new Title + { + TitleNumber = title.Index, + Duration = new TimeSpan(0, title.Duration.Hours, title.Duration.Minutes, title.Duration.Seconds), + Resolution = new Size(title.Geometry.Width, title.Geometry.Height), + AngleCount = title.AngleCount, + ParVal = new Size(title.Geometry.PAR.Num, title.Geometry.PAR.Den), + AutoCropDimensions = new Cropping + { + Top = title.Crop[0], + Bottom = title.Crop[1], + Left = title.Crop[2], + Right = title.Crop[3] + }, + Fps = ((double)title.FrameRate.Num) / title.FrameRate.Den, + SourceName = title.Path, + MainTitle = titles.MainFeature == title.Index, + Playlist = title.Type == 1 ? string.Format(" {0:d5}.MPLS", title.Playlist).Trim() : null, + FramerateNumerator = title.FrameRate.Num, + FramerateDenominator = title.FrameRate.Den + }; + + int currentTrack = 1; + foreach (SourceChapter chapter in title.ChapterList) + { + string chapterName = !string.IsNullOrEmpty(chapter.Name) ? chapter.Name : string.Empty; + converted.Chapters.Add(new Chapter(currentTrack, chapterName, new TimeSpan(chapter.Duration.Hours, chapter.Duration.Minutes, chapter.Duration.Seconds))); + currentTrack++; + } + + int currentAudioTrack = 1; + foreach (SourceAudioTrack track in title.AudioList) + { + converted.AudioTracks.Add(new Audio(currentAudioTrack, track.Language, track.LanguageCode, track.Description, string.Empty, track.SampleRate, track.BitRate)); + currentAudioTrack++; + } + + int currentSubtitleTrack = 1; + foreach (SourceSubtitleTrack track in title.SubtitleList) + { + SubtitleType convertedType = new SubtitleType(); + + switch (track.Source) + { + case 0: + convertedType = SubtitleType.VobSub; + break; + case 4: + convertedType = SubtitleType.UTF8Sub; + break; + case 5: + convertedType = SubtitleType.TX3G; + break; + case 6: + convertedType = SubtitleType.SSA; + break; + case 1: + convertedType = SubtitleType.SRT; + break; + case 2: + convertedType = SubtitleType.CC; + break; + case 3: + convertedType = SubtitleType.CC; + break; + case 7: + convertedType = SubtitleType.PGS; + break; + } + + bool canBurn = HBFunctions.hb_subtitle_can_burn(track.Source) > 0; + bool canSetForcedOnly = HBFunctions.hb_subtitle_can_force(track.Source) > 0; + + converted.Subtitles.Add(new Subtitle(track.Source, currentSubtitleTrack, track.Language, track.LanguageCode, convertedType, canBurn, canSetForcedOnly)); + currentSubtitleTrack++; + } + + titleList.Add(converted); + } + + return titleList; + } + + /// <summary> + /// The log message. + /// </summary> + /// <param name="message"> + /// The message. + /// </param> + private void LogMessage(string message) + { + lock (LogLock) + { + if (this.scanLog != null) + { + this.scanLog.WriteLine(message); + } + + this.logging.AppendLine(message); + } + } + + /// <summary> + /// The service log message. + /// </summary> + /// <param name="message"> + /// The message. + /// </param> + protected void ServiceLogMessage(string message) + { + this.LogMessage(string.Format("# {0}", message)); + } + #endregion + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Scan/Model/Audio.cs b/win/CS/HandBrakeWPF/Services/Scan/Model/Audio.cs new file mode 100644 index 000000000..1f0a2af98 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Scan/Model/Audio.cs @@ -0,0 +1,181 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="Audio.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// An object represending an AudioTrack associated with a Title, in a DVD +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Scan.Model +{ + using System; + + /// <summary> + /// An object represending an AudioTrack associated with a Title, in a DVD + /// </summary> + [Serializable] + public class Audio + { + /// <summary> + /// Initializes a new instance of the <see cref="Audio"/> class. + /// </summary> + public Audio() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="Audio"/> class. + /// </summary> + /// <param name="trackNumber"> + /// The track number. + /// </param> + /// <param name="language"> + /// The language. + /// </param> + /// <param name="languageCode"> + /// The language code. + /// </param> + /// <param name="description"> + /// The description. + /// </param> + /// <param name="format"> + /// The format. + /// </param> + /// <param name="sampleRate"> + /// The sample rate. + /// </param> + /// <param name="bitrate"> + /// The bitrate. + /// </param> + public Audio(int trackNumber, string language, string languageCode, string description, string format, int sampleRate, int bitrate) + { + this.TrackNumber = trackNumber; + this.Language = language; + this.LanguageCode = languageCode; + this.Description = description; + this.Format = format; + this.SampleRate = sampleRate; + this.Bitrate = bitrate; + } + + /// <summary> + /// Gets or sets The track number of this Audio Track + /// </summary> + public int TrackNumber { get; set; } + + /// <summary> + /// Gets or sets The language (if detected) of this Audio Track + /// </summary> + public string Language { get; set; } + + /// <summary> + /// Gets or sets LanguageCode. + /// </summary> + public string LanguageCode { get; set; } + + /// <summary> + /// Gets or sets Description. + /// </summary> + public string Description { get; set; } + + /// <summary> + /// Gets or sets The primary format of this Audio Track + /// </summary> + public string Format { get; set; } + + /// <summary> + /// Gets or sets The frequency (in MHz) of this Audio Track + /// </summary> + public int SampleRate { get; set; } + + /// <summary> + /// Gets or sets The bitrate (in kbps) of this Audio Track + /// </summary> + public int Bitrate { get; set; } + + /// <summary> + /// Override of the ToString method to make this object easier to use in the UI + /// </summary> + /// <returns>A string formatted as: {track #} {language} ({format}) ({sub-format})</returns> + public override string ToString() + { + if (this.Description == "None Found") + { + return this.Description; + } + + return string.Format("{0} {1}", this.TrackNumber, this.Description); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="other"> + /// The other. + /// </param> + /// <returns> + /// The System.Boolean. + /// </returns> + public bool Equals(Audio other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + return other.TrackNumber == this.TrackNumber && object.Equals(other.Language, this.Language) && object.Equals(other.LanguageCode, this.LanguageCode) && object.Equals(other.Format, this.Format); + } + + /// <summary> + /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>. + /// </summary> + /// <returns> + /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false. + /// </returns> + /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><filterpriority>2</filterpriority> + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != typeof(Audio)) + { + return false; + } + + return this.Equals((Audio)obj); + } + + /// <summary> + /// Serves as a hash function for a particular type. + /// </summary> + /// <returns> + /// A hash code for the current <see cref="T:System.Object"/>. + /// </returns> + /// <filterpriority>2</filterpriority> + public override int GetHashCode() + { + unchecked + { + int result = this.TrackNumber; + result = (result * 397) ^ (this.Language != null ? this.Language.GetHashCode() : 0); + result = (result * 397) ^ (this.LanguageCode != null ? this.LanguageCode.GetHashCode() : 0); + result = (result * 397) ^ (this.Format != null ? this.Format.GetHashCode() : 0); + return result; + } + } + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Scan/Model/Chapter.cs b/win/CS/HandBrakeWPF/Services/Scan/Model/Chapter.cs new file mode 100644 index 000000000..bc817a29c --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Scan/Model/Chapter.cs @@ -0,0 +1,70 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="Chapter.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// An object representing a Chapter aosciated with a Title, in a DVD +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Scan.Model +{ + using System; + using System.Globalization; + + /// <summary> + /// An object representing a Chapter aosciated with a Title, in a DVD + /// </summary> + public class Chapter + { + /// <summary> + /// Initializes a new instance of the <see cref="Chapter"/> class. + /// </summary> + public Chapter() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="Chapter"/> class. + /// </summary> + /// <param name="number"> + /// The number. + /// </param> + /// <param name="name"> + /// The name. + /// </param> + /// <param name="duration"> + /// The duration. + /// </param> + public Chapter(int number, string name, TimeSpan duration) + { + this.ChapterName = name; + this.ChapterNumber = number; + this.Duration = duration; + } + + /// <summary> + /// Gets or sets The number of this Chapter, in regards to it's parent Title + /// </summary> + public int ChapterNumber { get; set; } + + /// <summary> + /// Gets or sets ChapterName. + /// </summary> + public string ChapterName { get; set; } + + /// <summary> + /// Gets or sets The length in time this Chapter spans + /// </summary> + public TimeSpan Duration { get; set; } + + /// <summary> + /// Override of the ToString method to make this object easier to use in the UI + /// </summary> + /// <returns>A string formatted as: {chapter #}</returns> + public override string ToString() + { + return this.ChapterNumber.ToString(CultureInfo.InvariantCulture); + } + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Scan/Model/Source.cs b/win/CS/HandBrakeWPF/Services/Scan/Model/Source.cs new file mode 100644 index 000000000..b8e3bcdaf --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Scan/Model/Source.cs @@ -0,0 +1,57 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="Source.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// An object representing a scanned DVD +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Scan.Model +{ + using System.Collections.Generic; + using System.Runtime.Serialization; + using System.Xml.Serialization; + + /// <summary> + /// An object representing a scanned DVD + /// </summary> + [DataContract] + public class Source + { + /// <summary> + /// Initializes a new instance of the <see cref="Source"/> class. + /// Default constructor for this object + /// </summary> + public Source() + { + this.Titles = new List<Title>(); + } + + /// <summary> + /// Gets or sets ScanPath. + /// The Path used by the Scan Service. + /// </summary> + [DataMember] + public string ScanPath { get; set; } + + /// <summary> + /// Gets or sets Titles. A list of titles from the source + /// </summary> + [DataMember] + [XmlIgnore] + public List<Title> Titles { get; set; } + + /// <summary> + /// Copy this Source to another Source Model + /// </summary> + /// <param name="source"> + /// The source. + /// </param> + public void CopyTo(Source source) + { + source.Titles = this.Titles; + source.ScanPath = this.ScanPath; + } + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Scan/Model/Subtitle.cs b/win/CS/HandBrakeWPF/Services/Scan/Model/Subtitle.cs new file mode 100644 index 000000000..920ef711e --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Scan/Model/Subtitle.cs @@ -0,0 +1,207 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="Subtitle.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// An object that represents a subtitle associated with a Title, in a DVD +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Scan.Model +{ + using System; + using System.Xml.Serialization; + + using HandBrake.ApplicationServices.Utilities; + + using HandBrakeWPF.Services.Encode.Model.Models; + + /// <summary> + /// An object that represents a subtitle associated with a Title, in a DVD + /// </summary> + public class Subtitle + { + /// <summary> + /// Initializes a new instance of the <see cref="Subtitle"/> class. + /// </summary> + public Subtitle() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="Subtitle"/> class. + /// </summary> + /// <param name="sourceId"> + /// The source Id. + /// </param> + /// <param name="trackNumber"> + /// The track number. + /// </param> + /// <param name="language"> + /// The language. + /// </param> + /// <param name="languageCode"> + /// The language code. + /// </param> + /// <param name="subtitleType"> + /// The subtitle type. + /// </param> + /// <param name="canBurn"> + /// The can Burn. + /// </param> + /// <param name="canForce"> + /// The can Force. + /// </param> + public Subtitle(int sourceId, int trackNumber, string language, string languageCode, SubtitleType subtitleType, bool canBurn, bool canForce) + { + this.SourceId = sourceId; + this.TrackNumber = trackNumber; + this.Language = language; + this.LanguageCode = languageCode; + this.SubtitleType = subtitleType; + this.CanBurnIn = canBurn; + this.CanForce = canForce; + } + + /// <summary> + /// Gets or sets the source id. + /// </summary> + public int SourceId { get; set; } + + /// <summary> + /// Gets or sets the track number of this Subtitle + /// </summary> + public int TrackNumber { get; set; } + + /// <summary> + /// Gets or sets the The language (if detected) of this Subtitle + /// </summary> + public string Language { get; set; } + + /// <summary> + /// Gets or sets the Langauage Code + /// </summary> + public string LanguageCode { get; set; } + + /// <summary> + /// Gets the language code clean. + /// TODO Remove this after fixing language code. + /// </summary> + public string LanguageCodeClean + { + get + { + if (this.LanguageCode != null) + { + return this.LanguageCode.Replace("iso639-2: ", string.Empty).Trim(); + } + return string.Empty; + } + } + + /// <summary> + /// Gets a value indicating whether can burn in. + /// </summary> + [XmlIgnore] + public bool CanBurnIn { get; private set; } + + /// <summary> + /// Gets a value indicating whether can force. + /// </summary> + [XmlIgnore] + public bool CanForce { get; private set; } + + /// <summary> + /// Gets or sets the Subtitle Type + /// </summary> + public SubtitleType SubtitleType { get; set; } + + /// <summary> + /// Gets Subtitle Type + /// </summary> + public string TypeString + { + get + { + return EnumHelper<Enum>.GetDescription(this.SubtitleType); + } + } + + /// <summary> + /// Override of the ToString method to make this object easier to use in the UI + /// </summary> + /// <returns>A string formatted as: {track #} {language}</returns> + public override string ToString() + { + return this.SubtitleType == SubtitleType.ForeignAudioSearch ? "Foreign Audio Scan" : string.Format("{0} {1} ({2})", this.TrackNumber, this.Language, this.TypeString); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="other"> + /// The other. + /// </param> + /// <returns> + /// The System.Boolean. + /// </returns> + public bool Equals(Subtitle other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return other.TrackNumber == this.TrackNumber && object.Equals(other.Language, this.Language) && object.Equals(other.LanguageCode, this.LanguageCode) && object.Equals(other.SubtitleType, this.SubtitleType); + } + + /// <summary> + /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>. + /// </summary> + /// <returns> + /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false. + /// </returns> + /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><filterpriority>2</filterpriority> + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != typeof(Subtitle)) + { + return false; + } + + return this.Equals((Subtitle)obj); + } + + /// <summary> + /// Serves as a hash function for a particular type. + /// </summary> + /// <returns> + /// A hash code for the current <see cref="T:System.Object"/>. + /// </returns> + /// <filterpriority>2</filterpriority> + public override int GetHashCode() + { + unchecked + { + int result = this.TrackNumber; + result = (result * 397) ^ (this.Language != null ? this.Language.GetHashCode() : 0); + result = (result * 397) ^ (this.LanguageCode != null ? this.LanguageCode.GetHashCode() : 0); + result = (result * 397) ^ this.SubtitleType.GetHashCode(); + return result; + } + } + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Scan/Model/Title.cs b/win/CS/HandBrakeWPF/Services/Scan/Model/Title.cs new file mode 100644 index 000000000..32fddb36d --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Scan/Model/Title.cs @@ -0,0 +1,159 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="Title.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// An object that represents a single Title of a DVD +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Scan.Model +{ + using System; + using System.Collections.Generic; + using System.Linq; + + using HandBrake.ApplicationServices.Interop.Model; + + /// <summary> + /// An object that represents a single Title of a DVD + /// </summary> + public class Title + { + /// <summary> + /// Initializes a new instance of the <see cref="Title"/> class. + /// </summary> + public Title() + { + this.AudioTracks = new List<Audio>(); + this.Chapters = new List<Chapter>(); + this.Subtitles = new List<Subtitle>(); + } + + #region Properties + + /// <summary> + /// Gets or sets a Collection of chapters in this Title + /// </summary> + public List<Chapter> Chapters { get; set; } + + /// <summary> + /// Gets or sets a Collection of audio tracks associated with this Title + /// </summary> + public List<Audio> AudioTracks { get; set; } + + /// <summary> + /// Gets or sets a Collection of subtitles associated with this Title + /// </summary> + public List<Subtitle> Subtitles { get; set; } + + /// <summary> + /// Gets or sets The track number of this Title + /// </summary> + public int TitleNumber { get; set; } + + /// <summary> + /// Gets or sets the type. + /// HB_DVD_TYPE, HB_BD_TYPE, HB_STREAM_TYPE, HB_FF_STREAM_TYPE + /// </summary> + public int Type { get; set; } + + /// <summary> + /// Gets or sets Playlist. + /// </summary> + public string Playlist { get; set; } + + /// <summary> + /// Gets or sets the length in time of this Title + /// </summary> + public TimeSpan Duration { get; set; } + + /// <summary> + /// Gets or sets the resolution (width/height) of this Title + /// </summary> + public Size Resolution { get; set; } + + /// <summary> + /// Gets or sets the aspect ratio of this Title + /// </summary> + public decimal AspectRatio { get; set; } + + /// <summary> + /// Gets or sets AngleCount. + /// </summary> + public int AngleCount { get; set; } + + /// <summary> + /// Gets or sets Par Value + /// </summary> + public Size ParVal { get; set; } + + /// <summary> + /// Gets or sets the automatically detected crop region for this Title. + /// This is an int array with 4 items in it as so: + /// 0: T + /// 1: B + /// 2: L + /// 3: R + /// </summary> + public Cropping AutoCropDimensions { get; set; } + + /// <summary> + /// Gets or sets the FPS of the source. + /// </summary> + public double Fps { get; set; } + + /// <summary> + /// Gets or sets the video frame rate numerator. + /// </summary> + public int FramerateNumerator { get; set; } + + /// <summary> + /// Gets or sets the video frame rate denominator. + /// </summary> + public int FramerateDenominator { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this is a MainTitle. + /// </summary> + public bool MainTitle { get; set; } + + /// <summary> + /// Gets or sets the Source Name + /// </summary> + public string SourceName { get; set; } + + #endregion + + /// <summary> + /// Calcuate the Duration + /// </summary> + /// <param name="startPoint">The Start Point (Chapters)</param> + /// <param name="endPoint">The End Point (Chapters)</param> + /// <returns>A Timespan</returns> + public TimeSpan CalculateDuration(int startPoint, int endPoint) + { + IEnumerable<Chapter> chapers = + this.Chapters.Where(c => c.ChapterNumber >= startPoint && c.ChapterNumber <= endPoint); + + TimeSpan duration = TimeSpan.FromSeconds(0.0); + duration = chapers.Aggregate(duration, (current, chapter) => current + chapter.Duration); + + return duration; + } + + /// <summary> + /// Override of the ToString method to provide an easy way to use this object in the UI + /// </summary> + /// <returns>A string representing this track in the format: {title #} (00:00:00)</returns> + public override string ToString() + { + if (!string.IsNullOrEmpty(this.Playlist) && !this.Playlist.StartsWith(" ")) + { + this.Playlist = string.Format(" {0}", this.Playlist); + } + + return string.Format("{0}{1} ({2:00}:{3:00}:{4:00})", this.TitleNumber, this.Playlist, this.Duration.Hours, this.Duration.Minutes, this.Duration.Seconds); + } + } +}
\ No newline at end of file |