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 | |
parent | efcddfdf4fc67f59bf09154a0c8d2d20ba61c895 (diff) |
AppServices tidyup
Moving the UI modelling and services to the GUI Project.
Diffstat (limited to 'win/CS/HandBrakeWPF/Services')
43 files changed, 5718 insertions, 17 deletions
diff --git a/win/CS/HandBrakeWPF/Services/Encode/EncodeBase.cs b/win/CS/HandBrakeWPF/Services/Encode/EncodeBase.cs new file mode 100644 index 000000000..83ac7a083 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/EncodeBase.cs @@ -0,0 +1,380 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="EncodeBase.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> +// A Base Class for the Encode Services. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode +{ + using System; + using System.Diagnostics; + using System.IO; + using System.Text; + + using HandBrake.ApplicationServices.Exceptions; + using HandBrake.ApplicationServices.Model; + using HandBrake.ApplicationServices.Utilities; + + using EncodeCompletedEventArgs = HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs; + using EncodeCompletedStatus = HandBrakeWPF.Services.Encode.Interfaces.EncodeCompletedStatus; + using EncodeProgessStatus = HandBrakeWPF.Services.Encode.Interfaces.EncodeProgessStatus; + using EncodeProgressEventArgs = HandBrakeWPF.Services.Encode.EventArgs.EncodeProgressEventArgs; + using EncodeTask = HandBrakeWPF.Services.Encode.Model.EncodeTask; + + /// <summary> + /// A Base Class for the Encode Services. + /// </summary> + public class EncodeBase + { + #region Private Variables + + /// <summary> + /// A Lock for the filewriter + /// </summary> + private static readonly object FileWriterLock = new object(); + + /// <summary> + /// The Log File Header + /// </summary> + private readonly StringBuilder header; + + /// <summary> + /// The Log Buffer + /// </summary> + private StringBuilder logBuffer; + + /// <summary> + /// The Log file writer + /// </summary> + private StreamWriter fileWriter; + + #endregion + + /// <summary> + /// Initializes a new instance of the <see cref="EncodeBase"/> class. + /// </summary> + public EncodeBase() + { + this.logBuffer = new StringBuilder(); + this.header = GeneralUtilities.CreateLogHeader(); + this.LogIndex = 0; + } + + #region Events + + /// <summary> + /// Fires when a new QueueTask starts + /// </summary> + public event EventHandler EncodeStarted; + + /// <summary> + /// Fires when a QueueTask finishes. + /// </summary> + public event EncodeCompletedStatus EncodeCompleted; + + /// <summary> + /// Encode process has progressed + /// </summary> + public event EncodeProgessStatus EncodeStatusChanged; + + #endregion + + #region Properties + + /// <summary> + /// Gets or sets a value indicating whether IsEncoding. + /// </summary> + public bool IsEncoding { get; protected 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 started an encode." + 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.logBuffer.ToString()) + ? noLog + : this.header + this.logBuffer.ToString(); + } + } + + /// <summary> + /// Gets the log index. + /// </summary> + public int LogIndex { get; private set; } + + /// <summary> + /// Gets LogBuffer. + /// </summary> + public StringBuilder LogBuffer + { + get + { + return this.logBuffer; + } + } + + #endregion + + #region Invoke Events + + /// <summary> + /// Invoke the Encode Status Changed Event. + /// </summary> + /// <param name="e"> + /// The EncodeProgressEventArgs. + /// </param> + public void InvokeEncodeStatusChanged(EncodeProgressEventArgs e) + { + EncodeProgessStatus handler = this.EncodeStatusChanged; + if (handler != null) + { + handler(this, e); + } + } + + /// <summary> + /// Invoke the Encode Completed Event + /// </summary> + /// <param name="e"> + /// The EncodeCompletedEventArgs. + /// </param> + public void InvokeEncodeCompleted(EncodeCompletedEventArgs e) + { + EncodeCompletedStatus handler = this.EncodeCompleted; + if (handler != null) + { + handler(this, e); + } + + this.LogIndex = 0; // Reset + } + + /// <summary> + /// Invoke the Encode Started Event + /// </summary> + /// <param name="e"> + /// The EventArgs. + /// </param> + public void InvokeEncodeStarted(System.EventArgs e) + { + EventHandler handler = this.EncodeStarted; + if (handler != null) + { + handler(this, e); + } + } + + #endregion + + #region Methods + + /// <summary> + /// Save a copy of the log to the users desired location or a default location + /// if this feature is enabled in options. + /// </summary> + /// <param name="destination"> + /// The Destination File Path + /// </param> + /// <param name="configuration"> + /// The configuration. + /// </param> + public void ProcessLogs(string destination, HBConfiguration configuration) + { + try + { + string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + + "\\HandBrake\\logs"; + string tempLogFile = Path.Combine(logDir, string.Format("last_encode_log{0}.txt", GeneralUtilities.ProcessId)); + + string encodeDestinationPath = Path.GetDirectoryName(destination); + string destinationFile = Path.GetFileName(destination); + string encodeLogFile = destinationFile + " " + + DateTime.Now.ToString().Replace("/", "-").Replace(":", "-") + ".txt"; + + // Make sure the log directory exists. + if (!Directory.Exists(logDir)) + { + Directory.CreateDirectory(logDir); + } + + // Copy the Log to HandBrakes log folder in the users applciation data folder. + File.Copy(tempLogFile, Path.Combine(logDir, encodeLogFile)); + + // Save a copy of the log file in the same location as the enocde. + if (configuration.SaveLogWithVideo) + { + File.Copy(tempLogFile, Path.Combine(encodeDestinationPath, encodeLogFile)); + } + + // Save a copy of the log file to a user specified location + if (Directory.Exists(configuration.SaveLogCopyDirectory) && configuration.SaveLogToCopyDirectory) + { + File.Copy( + tempLogFile, Path.Combine(configuration.SaveLogCopyDirectory, encodeLogFile)); + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); // This exception doesn't warrent user interaction, but it should be logged + } + } + + /// <summary> + /// Setup the logging. + /// </summary> + protected void SetupLogging() + { + this.ShutdownFileWriter(); + string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs"; + string logFile = Path.Combine(logDir, string.Format("last_encode_log{0}.txt", GeneralUtilities.ProcessId)); + string logFile2 = Path.Combine(logDir, string.Format("tmp_appReadable_log{0}.txt", GeneralUtilities.ProcessId)); + + try + { + this.logBuffer = new StringBuilder(); + + this.logBuffer.AppendLine(); + + // Clear the current Encode Logs) + if (File.Exists(logFile)) + { + File.Delete(logFile); + } + + if (File.Exists(logFile2)) + { + File.Delete(logFile2); + } + + lock (FileWriterLock) + { + this.fileWriter = new StreamWriter(logFile) { AutoFlush = true }; + this.fileWriter.WriteLine(this.header); + this.fileWriter.WriteLine(); + } + } + catch (Exception) + { + if (this.fileWriter != null) + { + lock (FileWriterLock) + { + this.fileWriter.Flush(); + this.fileWriter.Close(); + this.fileWriter.Dispose(); + } + } + + throw; + } + } + + /// <summary> + /// The service log message. + /// </summary> + /// <param name="message"> + /// The message. + /// </param> + protected void ServiceLogMessage(string message) + { + this.ProcessLogMessage(string.Format("# {0}", message)); + } + + /// <summary> + /// Process an Incomming Log Message. + /// </summary> + /// <param name="message"> + /// The message. + /// </param> + protected void ProcessLogMessage(string message) + { + if (!string.IsNullOrEmpty(message)) + { + try + { + this.LogIndex = this.LogIndex + 1; + + lock (this.LogBuffer) + { + this.LogBuffer.AppendLine(message); + } + + lock (FileWriterLock) + { + if (this.fileWriter != null && this.fileWriter.BaseStream.CanWrite) + { + this.fileWriter.WriteLine(message); + } + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); // This exception doesn't warrent user interaction, but it should be logged + } + } + } + + /// <summary> + /// Shutdown and Dispose of the File Writer. + /// </summary> + protected void ShutdownFileWriter() + { + try + { + lock (FileWriterLock) + { + if (this.fileWriter != null) + { + this.fileWriter.Flush(); + this.fileWriter.Close(); + this.fileWriter.Dispose(); + } + + this.fileWriter = null; + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); // This exception doesn't warrent user interaction, but it should be logged + } + } + + /// <summary> + /// Verify the Encode Destination path exists and if not, create it. + /// </summary> + /// <param name="task"> + /// The task. + /// </param> + /// <exception cref="Exception"> + /// If the creation fails, an exception is thrown. + /// </exception> + protected void VerifyEncodeDestinationPath(EncodeTask task) + { + // Make sure the path exists, attempt to create it if it doesn't + try + { + string path = Directory.GetParent(task.Destination).ToString(); + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + } + catch (Exception exc) + { + throw new GeneralApplicationException( + "Unable to create directory for the encoded output.", "Please verify that you have a valid path.", exc); + } + } + + #endregion + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Encode/EventArgs/EncodeCompletedEventArgs.cs b/win/CS/HandBrakeWPF/Services/Encode/EventArgs/EncodeCompletedEventArgs.cs new file mode 100644 index 000000000..ea334705d --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/EventArgs/EncodeCompletedEventArgs.cs @@ -0,0 +1,68 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="EncodeCompletedEventArgs.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 Progress Event Args +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.EventArgs +{ + using System; + using System.Runtime.Serialization; + + /// <summary> + /// Encode Progress Event Args + /// </summary> + [DataContract] + public class EncodeCompletedEventArgs : EventArgs + { + /// <summary> + /// Initializes a new instance of the <see cref="EncodeCompletedEventArgs"/> class. + /// </summary> + /// <param name="sucessful"> + /// The sucessful. + /// </param> + /// <param name="exception"> + /// The exception. + /// </param> + /// <param name="errorInformation"> + /// The error information. + /// </param> + /// <param name="filename"> + /// The filename. + /// </param> + public EncodeCompletedEventArgs(bool sucessful, Exception exception, string errorInformation, string filename) + { + this.Successful = sucessful; + this.Exception = exception; + this.ErrorInformation = errorInformation; + this.FileName = filename; + } + + /// <summary> + /// Gets or sets the file name. + /// </summary> + [DataMember] + public string FileName { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether Successful. + /// </summary> + [DataMember] + public bool Successful { get; set; } + + /// <summary> + /// Gets or sets Exception. + /// </summary> + [DataMember] + public Exception Exception { get; set; } + + /// <summary> + /// Gets or sets ErrorInformation. + /// </summary> + [DataMember] + public string ErrorInformation { get; set; } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/EventArgs/EncodeProgressEventArgs.cs b/win/CS/HandBrakeWPF/Services/Encode/EventArgs/EncodeProgressEventArgs.cs new file mode 100644 index 000000000..5d3d12791 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/EventArgs/EncodeProgressEventArgs.cs @@ -0,0 +1,63 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="EncodeProgressEventArgs.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 Progress Event Args +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.EventArgs +{ + using System; + using System.Runtime.Serialization; + + /// <summary> + /// Encode Progress Event Args + /// </summary> + [DataContract] + public class EncodeProgressEventArgs : EventArgs + { + /// <summary> + /// Gets or sets PercentComplete. + /// </summary> + [DataMember] + public double PercentComplete { get; set; } + + /// <summary> + /// Gets or sets CurrentFrameRate. + /// </summary> + [DataMember] + public double CurrentFrameRate { get; set; } + + /// <summary> + /// Gets or sets AverageFrameRate. + /// </summary> + [DataMember] + public double AverageFrameRate { get; set; } + + /// <summary> + /// Gets or sets EstimatedTimeLeft. + /// </summary> + [DataMember] + public TimeSpan EstimatedTimeLeft { get; set; } + + /// <summary> + /// Gets or sets Task. + /// </summary> + [DataMember] + public int Task { get; set; } + + /// <summary> + /// Gets or sets TaskCount. + /// </summary> + [DataMember] + public int TaskCount { get; set; } + + /// <summary> + /// Gets or sets ElapsedTime. + /// </summary> + [DataMember] + public TimeSpan ElapsedTime { get; set; } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Factories/EncodeFactory.cs b/win/CS/HandBrakeWPF/Services/Encode/Factories/EncodeFactory.cs new file mode 100644 index 000000000..8c60024f6 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Factories/EncodeFactory.cs @@ -0,0 +1,542 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="EncodeFactory.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> +// The encode factory. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Factories +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Runtime.InteropServices; + + using HandBrake.ApplicationServices.Interop; + using HandBrake.ApplicationServices.Interop.HbLib; + using HandBrake.ApplicationServices.Interop.Helpers; + using HandBrake.ApplicationServices.Interop.Json.Encode; + using HandBrake.ApplicationServices.Interop.Json.Shared; + using HandBrake.ApplicationServices.Interop.Model.Encoding; + using HandBrake.ApplicationServices.Model; + using HandBrake.ApplicationServices.Utilities; + + using AudioEncoder = HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder; + using AudioEncoderRateType = HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType; + using AudioTrack = HandBrakeWPF.Services.Encode.Model.Models.AudioTrack; + using ChapterMarker = HandBrakeWPF.Services.Encode.Model.Models.ChapterMarker; + using EncodeTask = HandBrakeWPF.Services.Encode.Model.EncodeTask; + using FramerateMode = HandBrakeWPF.Services.Encode.Model.Models.FramerateMode; + using OutputFormat = HandBrakeWPF.Services.Encode.Model.Models.OutputFormat; + using PointToPointMode = HandBrakeWPF.Services.Encode.Model.Models.PointToPointMode; + using Subtitle = HandBrake.ApplicationServices.Interop.Json.Encode.Subtitles; + using SubtitleTrack = HandBrakeWPF.Services.Encode.Model.Models.SubtitleTrack; + + /// <summary> + /// This factory takes the internal EncodeJob object and turns it into a set of JSON models + /// that can be deserialized by libhb. + /// </summary> + internal class EncodeFactory + { + /* + * TODO: + * 1. OpenCL and HWD Support + * 2. Rotate Support + */ + + /// <summary> + /// The create. + /// </summary> + /// <param name="job"> + /// The encode job. + /// </param> + /// <param name="configuration"> + /// The configuration. + /// </param> + /// <returns> + /// The <see cref="JsonEncodeObject"/>. + /// </returns> + internal static JsonEncodeObject Create(EncodeTask job, HBConfiguration configuration) + { + JsonEncodeObject encode = new JsonEncodeObject + { + SequenceID = 0, + Audio = CreateAudio(job), + Destination = CreateDestination(job), + Filters = CreateFilters(job), + PAR = CreatePAR(job), + Metadata = CreateMetadata(job), + Source = CreateSource(job, configuration), + Subtitle = CreateSubtitle(job), + Video = CreateVideo(job, configuration) + }; + + return encode; + } + + /// <summary> + /// The create source. + /// </summary> + /// <param name="job"> + /// The job. + /// </param> + /// <param name="configuration"> + /// The configuration. + /// </param> + /// <returns> + /// The <see cref="Source"/>. + /// </returns> + private static Source CreateSource(EncodeTask job, HBConfiguration configuration) + { + Range range = new Range(); + switch (job.PointToPointMode) + { + case PointToPointMode.Chapters: + range.Type = "chapter"; + range.Start = job.StartPoint; + range.End = job.EndPoint; + break; + case PointToPointMode.Seconds: + range.Type = "time"; + range.Start = job.StartPoint * 90000; + range.End = (job.EndPoint - job.StartPoint) * 90000; + break; + case PointToPointMode.Frames: + range.Type = "frame"; + range.Start = job.StartPoint; + range.End = job.EndPoint; + break; + case PointToPointMode.Preview: + range.Type = "preview"; + range.Start = job.PreviewEncodeStartAt; + range.SeekPoints = configuration.PreviewScanCount; + range.End = job.PreviewEncodeDuration * 90000; + break; + } + + Source source = new Source + { + Title = job.Title, + Range = range, + Angle = job.Angle, + Path = job.Source, + }; + return source; + } + + /// <summary> + /// The create destination. + /// </summary> + /// <param name="job"> + /// The job. + /// </param> + /// <returns> + /// The <see cref="Destination"/>. + /// </returns> + private static Destination CreateDestination(EncodeTask job) + { + Destination destination = new Destination + { + File = job.Destination, + Mp4Options = new Mp4Options + { + IpodAtom = job.IPod5GSupport, + Mp4Optimize = job.OptimizeMP4 + }, + ChapterMarkers = job.IncludeChapterMarkers, + Mux = HBFunctions.hb_container_get_from_name(job.OutputFormat == OutputFormat.Mp4 ? "av_mp4" : "av_mkv"), // TODO tidy up. + ChapterList = new List<Chapter>() + }; + + if (job.IncludeChapterMarkers) + { + foreach (ChapterMarker item in job.ChapterNames) + { + Chapter chapter = new Chapter { Name = item.ChapterName }; + destination.ChapterList.Add(chapter); + } + } + + return destination; + } + + /// <summary> + /// Create the PAR object + /// </summary> + /// <param name="job"> + /// The Job + /// </param> + /// <returns> + /// The produced PAR object. + /// </returns> + private static PAR CreatePAR(EncodeTask job) + { + return new PAR { Num = job.PixelAspectX, Den = job.PixelAspectY }; + } + + /// <summary> + /// The create subtitle. + /// </summary> + /// <param name="job"> + /// The job. + /// </param> + /// <returns> + /// The <see cref="HandBrake.ApplicationServices.Interop.Json.Encode.Subtitles"/>. + /// </returns> + private static Subtitle CreateSubtitle(EncodeTask job) + { + Subtitles subtitle = new Subtitles + { + Search = + new SubtitleSearch + { + Enable = false, + Default = false, + Burn = false, + Forced = false + }, + SubtitleList = new List<HandBrake.ApplicationServices.Interop.Json.Encode.SubtitleTrack>() + }; + + foreach (SubtitleTrack item in job.SubtitleTracks) + { + if (!item.IsSrtSubtitle) + { + // Handle Foreign Audio Search + if (item.SourceTrack.TrackNumber == 0) + { + subtitle.Search.Enable = true; + subtitle.Search.Burn = item.Burned; + subtitle.Search.Default = item.Default; + subtitle.Search.Forced = item.Forced; + } + else + { + HandBrake.ApplicationServices.Interop.Json.Encode.SubtitleTrack track = new HandBrake.ApplicationServices.Interop.Json.Encode.SubtitleTrack + { + Burn = item.Burned, + Default = item.Default, + Forced = item.Forced, + ID = item.SourceTrack.TrackNumber, + Track = (item.SourceTrack.TrackNumber - 1) + }; + + subtitle.SubtitleList.Add(track); + } + } + else + { + HandBrake.ApplicationServices.Interop.Json.Encode.SubtitleTrack track = new HandBrake.ApplicationServices.Interop.Json.Encode.SubtitleTrack + { + Track = -1, // Indicates SRT + Default = item.Default, + Offset = item.SrtOffset, + Burn = item.Burned, + SRT = + new SRT + { + Filename = item.SrtPath, + Codeset = item.SrtCharCode, + Language = item.SrtLang + } + }; + + subtitle.SubtitleList.Add(track); + } + } + + return subtitle; + } + + /// <summary> + /// The create video. + /// </summary> + /// <param name="job"> + /// The job. + /// </param> + /// <param name="configuration"> + /// The configuration. + /// </param> + /// <returns> + /// The <see cref="Video"/>. + /// </returns> + private static Video CreateVideo(EncodeTask job, HBConfiguration configuration) + { + Video video = new Video(); + + HBVideoEncoder videoEncoder = HandBrakeEncoderHelpers.VideoEncoders.FirstOrDefault(e => e.ShortName == EnumHelper<VideoEncoder>.GetShortName(job.VideoEncoder)); + Validate.NotNull(videoEncoder, "Video encoder " + job.VideoEncoder + " not recognized."); + if (videoEncoder != null) + { + video.Encoder = videoEncoder.Id; + } + + string advancedOptions = job.ShowAdvancedTab ? job.AdvancedEncoderOptions : string.Empty; + if (!string.IsNullOrEmpty(advancedOptions)) + { + video.Options = advancedOptions; + } + else + { + video.Level = job.VideoLevel != null ? job.VideoLevel.ShortName : null; + video.Options = job.ExtraAdvancedArguments; + video.Preset = job.VideoPreset != null ? job.VideoPreset.ShortName : null; + video.Profile = job.VideoProfile != null ? job.VideoProfile.ShortName : null; + } + + if (job.VideoEncodeRateType == VideoEncodeRateType.ConstantQuality) video.Quality = job.Quality; + if (job.VideoEncodeRateType == VideoEncodeRateType.AverageBitrate) + { + video.Bitrate = job.VideoBitrate; + video.TwoPass = job.TwoPass; + video.Turbo = job.TurboFirstPass; + } + + if (job.VideoTunes != null && job.VideoTunes.Count > 0) + { + foreach (var item in job.VideoTunes) + { + video.Tune += string.IsNullOrEmpty(video.Tune) ? item.ShortName : "," + item.ShortName; + } + } + + video.OpenCL = configuration.ScalingMode == VideoScaler.BicubicCl; + video.HWDecode = configuration.EnableDxva; + video.QSV.Decode = !configuration.DisableQuickSyncDecoding; + + return video; + } + + /// <summary> + /// The create audio. + /// </summary> + /// <param name="job"> + /// The job. + /// </param> + /// <returns> + /// The <see cref="Audio"/>. + /// </returns> + private static Audio CreateAudio(EncodeTask job) + { + Audio audio = new Audio(); + + List<uint> copyMaskList = new List<uint>(); + if (job.AllowedPassthruOptions.AudioAllowAACPass) copyMaskList.Add(NativeConstants.HB_ACODEC_AAC_PASS); + if (job.AllowedPassthruOptions.AudioAllowAC3Pass) copyMaskList.Add(NativeConstants.HB_ACODEC_AC3_PASS); + if (job.AllowedPassthruOptions.AudioAllowDTSHDPass) copyMaskList.Add(NativeConstants.HB_ACODEC_DCA_HD_PASS); + if (job.AllowedPassthruOptions.AudioAllowDTSPass) copyMaskList.Add(NativeConstants.HB_ACODEC_DCA_PASS); + if (job.AllowedPassthruOptions.AudioAllowEAC3Pass) copyMaskList.Add(NativeConstants.HB_ACODEC_EAC3_PASS); + if (job.AllowedPassthruOptions.AudioAllowFlacPass) copyMaskList.Add(NativeConstants.HB_ACODEC_FLAC_PASS); + if (job.AllowedPassthruOptions.AudioAllowMP3Pass) copyMaskList.Add(NativeConstants.HB_ACODEC_MP3_PASS); + if (job.AllowedPassthruOptions.AudioAllowTrueHDPass) copyMaskList.Add(NativeConstants.HB_ACODEC_TRUEHD_PASS); + audio.CopyMask = copyMaskList.ToArray(); + + HBAudioEncoder audioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<AudioEncoder>.GetShortName(job.AllowedPassthruOptions.AudioEncoderFallback)); + audio.FallbackEncoder = audioEncoder.Id; + + audio.AudioList = new List<HandBrake.ApplicationServices.Interop.Json.Encode.AudioTrack>(); + foreach (AudioTrack item in job.AudioTracks) + { + HBAudioEncoder encoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<AudioEncoder>.GetShortName(item.Encoder)); + Validate.NotNull(encoder, "Unrecognized audio encoder:" + item.Encoder); + + HBMixdown mixdown = HandBrakeEncoderHelpers.GetMixdown(EnumHelper<Mixdown>.GetShortName(item.MixDown)); + Validate.NotNull(mixdown, "Unrecognized audio mixdown:" + item.MixDown); + + HBRate sampleRate = HandBrakeEncoderHelpers.AudioSampleRates.FirstOrDefault(s => s.Name == item.SampleRate.ToString(CultureInfo.InvariantCulture)); + + HandBrake.ApplicationServices.Interop.Json.Encode.AudioTrack audioTrack = new HandBrake.ApplicationServices.Interop.Json.Encode.AudioTrack + { + Track = (item.Track.HasValue ? item.Track.Value : 0) - 1, + DRC = item.DRC, + Encoder = encoder.Id, + Gain = item.Gain, + Mixdown = mixdown.Id, + NormalizeMixLevel = false, + Samplerate = sampleRate != null ? sampleRate.Rate : 0, + Name = item.TrackName, + }; + + if (!item.IsPassthru) + { + if (item.EncoderRateType == AudioEncoderRateType.Quality) + { + audioTrack.Quality = item.Quality; + } + + if (item.EncoderRateType == AudioEncoderRateType.Bitrate) + { + audioTrack.Bitrate = item.Bitrate; + } + } + + audio.AudioList.Add(audioTrack); + } + + return audio; + } + + /// <summary> + /// The create filter. + /// </summary> + /// <param name="job"> + /// The job. + /// </param> + /// <returns> + /// The <see cref="Filters"/>. + /// </returns> + private static Filters CreateFilters(EncodeTask job) + { + Filters filter = new Filters + { + FilterList = new List<Filter>(), + Grayscale = job.Grayscale + }; + + // Detelecine + if (job.Detelecine != Detelecine.Off) + { + Filter filterItem = new Filter { ID = (int)hb_filter_ids.HB_FILTER_DETELECINE, Settings = job.CustomDetelecine }; + filter.FilterList.Add(filterItem); + } + + // Decomb + if (job.Decomb != Decomb.Off) + { + string options; + if (job.Decomb == Decomb.Fast) + { + options = "7:2:6:9:1:80"; + } + else if (job.Decomb == Decomb.Bob) + { + options = "455"; + } + else + { + options = job.CustomDecomb; + } + + Filter filterItem = new Filter { ID = (int)hb_filter_ids.HB_FILTER_DECOMB, Settings = options }; + filter.FilterList.Add(filterItem); + } + + // Deinterlace + if (job.Deinterlace != Deinterlace.Off) + { + string options; + if (job.Deinterlace == Deinterlace.Fast) + { + options = "0"; + } + else if (job.Deinterlace == Deinterlace.Slow) + { + options = "1"; + } + else if (job.Deinterlace == Deinterlace.Slower) + { + options = "3"; + } + else if (job.Deinterlace == Deinterlace.Bob) + { + options = "15"; + } + else + { + options = job.CustomDeinterlace; + } + + Filter filterItem = new Filter { ID = (int)hb_filter_ids.HB_FILTER_DEINTERLACE, Settings = options }; + filter.FilterList.Add(filterItem); + } + + // VFR / CFR + int fm = job.FramerateMode == FramerateMode.CFR ? 1 : job.FramerateMode == FramerateMode.PFR ? 2 : 0; + IntPtr frameratePrt = Marshal.StringToHGlobalAnsi(job.Framerate.ToString()); // TODO check culture + int vrate = HBFunctions.hb_video_framerate_get_from_name(frameratePrt); + + int? num = null; + int? den = null; + if (vrate > 0) + { + num = 27000000; + den = vrate; + } + + string framerateString = num.HasValue ? string.Format("{0}:{1}:{2}", fm, num, den) : string.Format("{0}", fm); // filter_cfr, filter_vrate.num, filter_vrate.den + + Filter framerateShaper = new Filter { ID = (int)hb_filter_ids.HB_FILTER_VFR, Settings = framerateString }; + filter.FilterList.Add(framerateShaper); + + // Deblock + if (job.Deblock >= 5) + { + Filter filterItem = new Filter { ID = (int)hb_filter_ids.HB_FILTER_DEBLOCK, Settings = job.Deblock.ToString() }; + filter.FilterList.Add(filterItem); + } + + // Denoise + if (job.Denoise != Denoise.Off) + { + hb_filter_ids id = job.Denoise == Denoise.hqdn3d + ? hb_filter_ids.HB_FILTER_HQDN3D + : hb_filter_ids.HB_FILTER_NLMEANS; + + string settings; + if (!string.IsNullOrEmpty(job.CustomDenoise)) + { + settings = job.CustomDenoise; + } + else + { + IntPtr settingsPtr = HBFunctions.hb_generate_filter_settings((int)id, job.DenoisePreset.ToString().ToLower().Replace(" ", string.Empty), job.DenoiseTune.ToString().ToLower().Replace(" ", string.Empty)); + settings = Marshal.PtrToStringAnsi(settingsPtr); + } + + Filter filterItem = new Filter { ID = (int)id, Settings = settings }; + filter.FilterList.Add(filterItem); + } + + // CropScale Filter + Filter cropScale = new Filter + { + ID = (int)hb_filter_ids.HB_FILTER_CROP_SCALE, + Settings = + string.Format( + "{0}:{1}:{2}:{3}:{4}:{5}", + job.Width, + job.Height, + job.Cropping.Top, + job.Cropping.Bottom, + job.Cropping.Left, + job.Cropping.Right) + }; + filter.FilterList.Add(cropScale); + + // Rotate + /* TODO NOT SUPPORTED YET. */ + + return filter; + } + + /// <summary> + /// The create meta data. + /// </summary> + /// <param name="job"> + /// The job. + /// </param> + /// <returns> + /// The <see cref="Metadata"/>. + /// </returns> + private static Metadata CreateMetadata(EncodeTask job) + { + Metadata metaData = new Metadata(); + + /* TODO NOT SUPPORTED YET. */ + return metaData; + } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoLevelFactory.cs b/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoLevelFactory.cs new file mode 100644 index 000000000..f233d203e --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoLevelFactory.cs @@ -0,0 +1,38 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="VideoLevelFactory.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> +// The video level factory. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Factories +{ + /// <summary> + /// The video tune factory. + /// </summary> + public class VideoLevelFactory + { + /// <summary> + /// The get display name for a given short name. + /// LibHB doesn't currently support this. + /// </summary> + /// <param name="shortName"> + /// The short name. + /// </param> + /// <returns> + /// The <see cref="string"/>. + /// </returns> + public static string GetDisplayName(string shortName) + { + switch (shortName) + { + case "auto": + return "Auto"; + } + + return shortName; + } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoPresetFactory.cs b/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoPresetFactory.cs new file mode 100644 index 000000000..491eb7c4e --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoPresetFactory.cs @@ -0,0 +1,63 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="VideoPresetFactory.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> +// The video preset factory. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Factories +{ + /// <summary> + /// The video tune factory. + /// </summary> + public class VideoPresetFactory + { + /// <summary> + /// The get display name for a given short name. + /// LibHB doesn't currently support this. + /// </summary> + /// <param name="shortName"> + /// The short name. + /// </param> + /// <returns> + /// The <see cref="string"/>. + /// </returns> + public static string GetDisplayName(string shortName) + { + switch (shortName) + { + case "ultrafast": + return "Ultrafast"; + case "superfast": + return "Superfast"; + case "veryfast": + return "Veryfast"; + case "faster": + return "Faster"; + case "fast": + return "Fast"; + case "medium": + return "Medium"; + case "slow": + return "Slow"; + case "slower": + return "Slower"; + case "veryslow": + return "VerySlow"; + case "placebo": + return "Placebo"; + + case "balanced": + return "Balanced"; + case "speed": + return "Speed"; + case "quality": + return "Quality"; + } + + return shortName; + } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoProfileFactory.cs b/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoProfileFactory.cs new file mode 100644 index 000000000..e9e5c7c75 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoProfileFactory.cs @@ -0,0 +1,48 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="VideoProfileFactory.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> +// The video profile factory. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Factories +{ + /// <summary> + /// The video profile factory. + /// </summary> + public class VideoProfileFactory + { + /// <summary> + /// The get display name for a given short name. + /// LibHB doesn't currently support this. + /// </summary> + /// <param name="shortName"> + /// The short name. + /// </param> + /// <returns> + /// The <see cref="string"/>. + /// </returns> + public static string GetDisplayName(string shortName) + { + switch (shortName) + { + case "auto": + return "Auto"; + case "main": + return "Main"; + case "high": + return "High"; + case "baseline": + return "Baseline"; + case "main10": + return "Main 10"; + case "mainstillpicture": + return "Main Still Picture"; + } + + return shortName; + } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoTuneFactory.cs b/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoTuneFactory.cs new file mode 100644 index 000000000..b221ceef6 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Factories/VideoTuneFactory.cs @@ -0,0 +1,54 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="VideoTuneFactory.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> +// The video tune factory. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Factories +{ + /// <summary> + /// The video tune factory. + /// </summary> + public class VideoTuneFactory + { + /// <summary> + /// The get display name for a given short name. + /// LibHB doesn't currently support this. + /// </summary> + /// <param name="shortName"> + /// The short name. + /// </param> + /// <returns> + /// The <see cref="string"/>. + /// </returns> + public static string GetDisplayName(string shortName) + { + switch (shortName) + { + case "auto": + return "Auto"; + case "film": + return "Film"; + case "animation": + return "Animation"; + case "grain": + return "Grain"; + case "stillimage": + return "Still Image"; + case "psnr": + return "PSNR"; + case "ssim": + return "SSIM"; + case "fastdecode": + return "Fast Decode"; + case "zerolatency": + return "Zero Latency"; + } + + return shortName; + } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs b/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs new file mode 100644 index 000000000..1e81ed5ed --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs @@ -0,0 +1,119 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="IEncode.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.Encode.Interfaces +{ + using System; + + using HandBrake.ApplicationServices.Model; + + using EncodeCompletedEventArgs = HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs; + using EncodeProgressEventArgs = HandBrakeWPF.Services.Encode.EventArgs.EncodeProgressEventArgs; + using EncodeTask = HandBrakeWPF.Services.Encode.Model.EncodeTask; + + /// <summary> + /// Encode Progess Status + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The EncodeProgressEventArgs. + /// </param> + public delegate void EncodeProgessStatus(object sender, EncodeProgressEventArgs e); + + /// <summary> + /// Encode Progess Status + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The EncodeProgressEventArgs. + /// </param> + public delegate void EncodeCompletedStatus(object sender, EncodeCompletedEventArgs e); + + /// <summary> + /// The IEncode Interface + /// </summary> + public interface IEncode + { + /// <summary> + /// Fires when a new Job starts + /// </summary> + event EventHandler EncodeStarted; + + /// <summary> + /// Fires when a job finishes. + /// </summary> + event EncodeCompletedStatus EncodeCompleted; + + /// <summary> + /// Encode process has progressed + /// </summary> + event EncodeProgessStatus EncodeStatusChanged; + + /// <summary> + /// Gets a value indicating whether IsEncoding. + /// </summary> + bool IsEncoding { get; } + + /// <summary> + /// Gets ActivityLog. + /// </summary> + string ActivityLog { get; } + + /// <summary> + /// Gets the log index. The current log row counter. + /// </summary> + int LogIndex { get; } + + /// <summary> + /// Gets a value indicating whether is pasued. + /// </summary> + bool IsPasued { get; } + + /// <summary> + /// Start with a LibHb EncodeJob Object + /// </summary> + /// <param name="job"> + /// The job. + /// </param> + /// <param name="configuration"> + /// The configuration. + /// </param> + void Start(EncodeTask job, HBConfiguration configuration); + + /// <summary> + /// The pause. + /// </summary> + void Pause(); + + /// <summary> + /// The resume. + /// </summary> + void Resume(); + + /// <summary> + /// Kill the process + /// </summary> + void Stop(); + + /// <summary> + /// Copy the log file to the desired destinations + /// </summary> + /// <param name="destination"> + /// The destination. + /// </param> + /// <param name="configuration"> + /// The configuration. + /// </param> + void ProcessLogs(string destination, HBConfiguration configuration); + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs b/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs new file mode 100644 index 000000000..caf1eff1d --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs @@ -0,0 +1,262 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="LibEncode.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> +// LibHB Implementation of IEncode +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode +{ + using System; + using System.Diagnostics; + + using HandBrake.ApplicationServices.Interop; + using HandBrake.ApplicationServices.Interop.EventArgs; + using HandBrake.ApplicationServices.Interop.Interfaces; + using HandBrake.ApplicationServices.Model; + + using HandBrakeWPF.Services.Encode.Factories; + + using EncodeTask = HandBrakeWPF.Services.Encode.Model.EncodeTask; + using IEncode = HandBrakeWPF.Services.Encode.Interfaces.IEncode; + + /// <summary> + /// LibHB Implementation of IEncode + /// </summary> + public class LibEncode : HandBrakeWPF.Services.Encode.EncodeBase, IEncode + { + #region Private Variables + + private static readonly object LogLock = new object(); + private IHandBrakeInstance instance; + private DateTime startTime; + private EncodeTask currentTask; + private HBConfiguration currentConfiguration; + + #endregion + + /// <summary> + /// Gets a value indicating whether is pasued. + /// </summary> + public bool IsPasued { get; private set; } + + /// <summary> + /// Start with a LibHb EncodeJob Object + /// </summary> + /// <param name="task"> + /// The task. + /// </param> + /// <param name="configuration"> + /// The configuration. + /// </param> + public void Start(EncodeTask task, HBConfiguration configuration) + { + try + { + // Setup + this.startTime = DateTime.Now; + this.currentTask = task; + this.currentConfiguration = configuration; + + // Create a new HandBrake instance + // Setup the HandBrake Instance + HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged; + HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged; + this.instance = HandBrakeInstanceManager.GetEncodeInstance(configuration.Verbosity); + this.instance.EncodeCompleted += this.InstanceEncodeCompleted; + this.instance.EncodeProgress += this.InstanceEncodeProgress; + + // Sanity Checking and Setup + if (this.IsEncoding) + { + throw new Exception("HandBrake is already encoding."); + } + + this.IsEncoding = true; + this.SetupLogging(); + + // Verify the Destination Path Exists, and if not, create it. + this.VerifyEncodeDestinationPath(task); + + this.ServiceLogMessage("Starting Encode ..."); + + // Get an EncodeJob object for the Interop Library + this.instance.StartEncode(EncodeFactory.Create(task, configuration)); + + // Fire the Encode Started Event + this.InvokeEncodeStarted(System.EventArgs.Empty); + + // Set the Process Priority + switch (configuration.ProcessPriority) + { + case "Realtime": + Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; + break; + case "High": + Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; + break; + case "Above Normal": + Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.AboveNormal; + break; + case "Normal": + Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Normal; + break; + case "Low": + Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Idle; + break; + default: + Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal; + break; + } + } + catch (Exception exc) + { + this.IsEncoding = false; + + this.ServiceLogMessage("Failed to start encoding ..." + Environment.NewLine + exc); + this.InvokeEncodeCompleted(new HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs(false, exc, "Unable to start encoding", task.Source)); + } + } + + /// <summary> + /// Pause the currently running encode. + /// </summary> + public void Pause() + { + if (this.instance != null) + { + this.instance.PauseEncode(); + this.ServiceLogMessage("Encode Paused"); + this.IsPasued = true; + } + } + + /// <summary> + /// Resume the currently running encode. + /// </summary> + public void Resume() + { + if (this.instance != null) + { + this.instance.ResumeEncode(); + this.ServiceLogMessage("Encode Resumed"); + this.IsPasued = false; + } + } + + /// <summary> + /// Kill the process + /// </summary> + public void Stop() + { + try + { + this.IsEncoding = false; + if (this.instance != null) + { + this.instance.StopEncode(); + this.ServiceLogMessage("Encode Stopped"); + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); + } + } + + #region HandBrakeInstance Event Handlers. + + /// <summary> + /// Log a message + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The MessageLoggedEventArgs. + /// </param> + private void HandBrakeInstanceErrorLogged(object sender, MessageLoggedEventArgs e) + { + lock (LogLock) + { + this.ProcessLogMessage(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) + { + lock (LogLock) + { + this.ProcessLogMessage(e.Message); + } + } + + /// <summary> + /// Encode Progress Event Handler + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The Interop.EncodeProgressEventArgs. + /// </param> + private void InstanceEncodeProgress(object sender, EncodeProgressEventArgs e) + { + HandBrakeWPF.Services.Encode.EventArgs.EncodeProgressEventArgs args = new HandBrakeWPF.Services.Encode.EventArgs.EncodeProgressEventArgs + { + AverageFrameRate = e.AverageFrameRate, + CurrentFrameRate = e.CurrentFrameRate, + EstimatedTimeLeft = e.EstimatedTimeLeft, + PercentComplete = e.FractionComplete * 100, + Task = e.Pass, + TaskCount = e.PassCount, + ElapsedTime = DateTime.Now - this.startTime, + }; + + this.InvokeEncodeStatusChanged(args); + } + + /// <summary> + /// Encode Completed Event Handler + /// </summary> + /// <param name="sender"> + /// The sender. + /// </param> + /// <param name="e"> + /// The e. + /// </param> + private void InstanceEncodeCompleted(object sender, EncodeCompletedEventArgs e) + { + this.IsEncoding = false; + this.ServiceLogMessage("Encode Completed ..."); + + // Stop Logging. + HandBrakeUtils.MessageLogged -= this.HandBrakeInstanceMessageLogged; + HandBrakeUtils.ErrorLogged -= this.HandBrakeInstanceErrorLogged; + + // Handling Log Data + this.ProcessLogs(this.currentTask.Destination, this.currentConfiguration); + + // Cleanup + this.ShutdownFileWriter(); + + // Raise the Encode Completed EVent. + this.InvokeEncodeCompleted( + e.Error + ? new HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs(false, null, string.Empty, this.currentTask.Destination) + : new HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs(true, null, string.Empty, this.currentTask.Destination)); + } + #endregion + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/EncodeTask.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/EncodeTask.cs new file mode 100644 index 000000000..e40def17f --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/EncodeTask.cs @@ -0,0 +1,557 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="EncodeTask.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 Encode Task +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Linq; + + using HandBrake.ApplicationServices.Interop.Model; + using HandBrake.ApplicationServices.Interop.Model.Encoding; + using HandBrake.ApplicationServices.Utilities; + + using AllowedPassthru = HandBrakeWPF.Services.Encode.Model.Models.AllowedPassthru; + using AudioEncoder = HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder; + using AudioTrack = HandBrakeWPF.Services.Encode.Model.Models.AudioTrack; + using ChapterMarker = HandBrakeWPF.Services.Encode.Model.Models.ChapterMarker; + using DenoisePreset = HandBrakeWPF.Services.Encode.Model.Models.DenoisePreset; + using DenoiseTune = HandBrakeWPF.Services.Encode.Model.Models.DenoiseTune; + using FramerateMode = HandBrakeWPF.Services.Encode.Model.Models.FramerateMode; + using OutputFormat = HandBrakeWPF.Services.Encode.Model.Models.OutputFormat; + using PointToPointMode = HandBrakeWPF.Services.Encode.Model.Models.PointToPointMode; + using SubtitleTrack = HandBrakeWPF.Services.Encode.Model.Models.SubtitleTrack; + using SubtitleType = HandBrakeWPF.Services.Encode.Model.Models.SubtitleType; + using VideoLevel = HandBrakeWPF.Services.Encode.Model.Models.Video.VideoLevel; + using VideoPreset = HandBrakeWPF.Services.Encode.Model.Models.Video.VideoPreset; + using VideoProfile = HandBrakeWPF.Services.Encode.Model.Models.Video.VideoProfile; + using VideoTune = HandBrakeWPF.Services.Encode.Model.Models.Video.VideoTune; + + /// <summary> + /// An Encode Task + /// </summary> + public class EncodeTask : PropertyChangedBase + { + #region Private Fields + + /// <summary> + /// The advanced panel enabled. + /// </summary> + private bool showAdvancedTab; + + #endregion + + /// <summary> + /// Initializes a new instance of the <see cref="EncodeTask"/> class. + /// </summary> + public EncodeTask() + { + this.Cropping = new Cropping(); + this.AudioTracks = new ObservableCollection<AudioTrack>(); + this.SubtitleTracks = new ObservableCollection<SubtitleTrack>(); + this.ChapterNames = new ObservableCollection<ChapterMarker>(); + this.AllowedPassthruOptions = new AllowedPassthru(); + this.Modulus = 16; + + this.VideoTunes = new List<VideoTune>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="EncodeTask"/> class. + /// Copy Constructor + /// </summary> + /// <param name="task"> + /// The task. + /// </param> + public EncodeTask(EncodeTask task) + { + this.AdvancedEncoderOptions = task.AdvancedEncoderOptions; + this.AllowedPassthruOptions = new AllowedPassthru(task.AllowedPassthruOptions); + this.Anamorphic = task.Anamorphic; + this.Angle = task.Angle; + + this.AudioTracks = new ObservableCollection<AudioTrack>(); + foreach (AudioTrack track in task.AudioTracks) + { + this.AudioTracks.Add(new AudioTrack(track, true)); + } + + this.ChapterNames = new ObservableCollection<ChapterMarker>(); + foreach (ChapterMarker track in task.ChapterNames) + { + this.ChapterNames.Add(new ChapterMarker(track)); + } + + this.ChapterMarkersFilePath = task.ChapterMarkersFilePath; + this.Cropping = new Cropping(task.Cropping); + this.CustomDecomb = task.CustomDecomb; + this.CustomDeinterlace = task.CustomDeinterlace; + this.CustomDenoise = task.CustomDenoise; + this.CustomDetelecine = task.CustomDetelecine; + this.Deblock = task.Deblock; + this.Decomb = task.Decomb; + this.Deinterlace = task.Deinterlace; + this.Denoise = task.Denoise; + this.DenoisePreset = task.DenoisePreset; + this.DenoiseTune = task.DenoiseTune; + this.Destination = task.Destination; + this.Detelecine = task.Detelecine; + this.DisplayWidth = task.DisplayWidth; + this.EndPoint = task.EndPoint; + this.Framerate = task.Framerate; + this.FramerateMode = task.FramerateMode; + this.Grayscale = task.Grayscale; + this.HasCropping = task.HasCropping; + this.Height = task.Height; + this.IncludeChapterMarkers = task.IncludeChapterMarkers; + this.IPod5GSupport = task.IPod5GSupport; + this.KeepDisplayAspect = task.KeepDisplayAspect; + this.MaxHeight = task.MaxHeight; + this.MaxWidth = task.MaxWidth; + this.Modulus = task.Modulus; + this.OptimizeMP4 = task.OptimizeMP4; + this.OutputFormat = task.OutputFormat; + this.PixelAspectX = task.PixelAspectX; + this.PixelAspectY = task.PixelAspectY; + this.PointToPointMode = task.PointToPointMode; + this.Quality = task.Quality; + this.Source = task.Source; + this.StartPoint = task.StartPoint; + + this.SubtitleTracks = new ObservableCollection<SubtitleTrack>(); + foreach (SubtitleTrack subtitleTrack in task.SubtitleTracks) + { + this.SubtitleTracks.Add(new SubtitleTrack(subtitleTrack)); + } + + this.Title = task.Title; + this.TurboFirstPass = task.TurboFirstPass; + this.TwoPass = task.TwoPass; + this.VideoBitrate = task.VideoBitrate; + this.VideoEncoder = task.VideoEncoder; + this.VideoEncodeRateType = task.VideoEncodeRateType; + this.Width = task.Width; + + this.VideoLevel = task.VideoLevel; + this.VideoProfile = task.VideoProfile; + this.VideoPreset = task.VideoPreset; + this.VideoTunes = task.VideoTunes; + this.ExtraAdvancedArguments = task.ExtraAdvancedArguments; + + this.ShowAdvancedTab = task.ShowAdvancedTab; + } + + #region Source + + /// <summary> + /// Gets or sets Source. + /// </summary> + public string Source { get; set; } + + /// <summary> + /// Gets or sets Title. + /// </summary> + public int Title { get; set; } + + /// <summary> + /// Gets or sets the Angle + /// </summary> + public int Angle { get; set; } + + /// <summary> + /// Gets or sets PointToPointMode. + /// </summary> + public PointToPointMode PointToPointMode { get; set; } + + /// <summary> + /// Gets or sets StartPoint. + /// </summary> + public int StartPoint { get; set; } + + /// <summary> + /// Gets or sets EndPoint. + /// </summary> + public int EndPoint { get; set; } + + #endregion + + #region Destination + + /// <summary> + /// Gets or sets Destination. + /// </summary> + public string Destination { get; set; } + + #endregion + + #region Output Settings + + /// <summary> + /// Gets or sets OutputFormat. + /// </summary> + public OutputFormat OutputFormat { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether Optimize. + /// </summary> + public bool OptimizeMP4 { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether IPod5GSupport. + /// </summary> + public bool IPod5GSupport { get; set; } + + #endregion + + #region Picture + + /// <summary> + /// Gets or sets Width. + /// </summary> + public int? Width { get; set; } + + /// <summary> + /// Gets or sets Height. + /// </summary> + public int? Height { get; set; } + + /// <summary> + /// Gets or sets MaxWidth. + /// </summary> + public int? MaxWidth { get; set; } + + /// <summary> + /// Gets or sets MaxHeight. + /// </summary> + public int? MaxHeight { get; set; } + + /// <summary> + /// Gets or sets Cropping. + /// </summary> + public Cropping Cropping { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether HasCropping. + /// </summary> + public bool HasCropping { get; set; } + + /// <summary> + /// Gets or sets Anamorphic. + /// </summary> + public Anamorphic Anamorphic { get; set; } + + /// <summary> + /// Gets or sets DisplayWidth. + /// </summary> + public double? DisplayWidth { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether KeepDisplayAspect. + /// </summary> + public bool KeepDisplayAspect { get; set; } + + /// <summary> + /// Gets or sets PixelAspectX. + /// </summary> + public int PixelAspectX { get; set; } + + /// <summary> + /// Gets or sets PixelAspectY. + /// </summary> + public int PixelAspectY { get; set; } + + /// <summary> + /// Gets or sets Modulus. + /// </summary> + public int? Modulus { get; set; } + + #endregion + + #region Filters + + /// <summary> + /// Gets or sets Deinterlace. + /// </summary> + public Deinterlace Deinterlace { get; set; } + + /// <summary> + /// Gets or sets CustomDeinterlace. + /// </summary> + public string CustomDeinterlace { get; set; } + + /// <summary> + /// Gets or sets Decomb. + /// </summary> + public Decomb Decomb { get; set; } + + /// <summary> + /// Gets or sets CustomDecomb. + /// </summary> + public string CustomDecomb { get; set; } + + /// <summary> + /// Gets or sets Detelecine. + /// </summary> + public Detelecine Detelecine { get; set; } + + /// <summary> + /// Gets or sets CustomDetelecine. + /// </summary> + public string CustomDetelecine { get; set; } + + /// <summary> + /// Gets or sets Denoise. + /// </summary> + public Denoise Denoise { get; set; } + + /// <summary> + /// Gets or sets the denoise preset. + /// </summary> + public DenoisePreset DenoisePreset { get; set; } + + /// <summary> + /// Gets or sets the denoise tune. + /// </summary> + public DenoiseTune DenoiseTune { get; set; } + + /// <summary> + /// Gets or sets CustomDenoise. + /// </summary> + public string CustomDenoise { get; set; } + + /// <summary> + /// Gets or sets Deblock. + /// </summary> + public int Deblock { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether Grayscale. + /// </summary> + public bool Grayscale { get; set; } + + #endregion + + #region Video + + /// <summary> + /// Gets or sets VideoEncodeRateType. + /// </summary> + public VideoEncodeRateType VideoEncodeRateType { get; set; } + + /// <summary> + /// Gets or sets the VideoEncoder + /// </summary> + public VideoEncoder VideoEncoder { get; set; } + + /// <summary> + /// Gets or sets the Video Encode Mode + /// </summary> + public FramerateMode FramerateMode { get; set; } + + /// <summary> + /// Gets or sets Quality. + /// </summary> + public double? Quality { get; set; } + + /// <summary> + /// Gets or sets VideoBitrate. + /// </summary> + public int? VideoBitrate { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether TwoPass. + /// </summary> + public bool TwoPass { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether TurboFirstPass. + /// </summary> + public bool TurboFirstPass { get; set; } + + /// <summary> + /// Gets or sets Framerate. + /// Null = Same as Source + /// </summary> + public double? Framerate { get; set; } + + #endregion + + #region Audio + + /// <summary> + /// Gets or sets AudioEncodings. + /// </summary> + public ObservableCollection<AudioTrack> AudioTracks { get; set; } + + /// <summary> + /// Gets or sets AllowedPassthruOptions. + /// </summary> + public AllowedPassthru AllowedPassthruOptions { get; set; } + + #endregion + + #region Subtitles + + /// <summary> + /// Gets or sets SubtitleTracks. + /// </summary> + public ObservableCollection<SubtitleTrack> SubtitleTracks { get; set; } + + #endregion + + #region Chapters + + /// <summary> + /// Gets or sets a value indicating whether IncludeChapterMarkers. + /// </summary> + public bool IncludeChapterMarkers { get; set; } + + /// <summary> + /// Gets or sets ChapterMarkersFilePath. + /// </summary> + public string ChapterMarkersFilePath { get; set; } + + /// <summary> + /// Gets or sets ChapterNames. + /// </summary> + public ObservableCollection<ChapterMarker> ChapterNames { get; set; } + + #endregion + + #region Advanced + + /// <summary> + /// Gets or sets AdvancedEncoderOptions. + /// </summary> + public string AdvancedEncoderOptions { get; set; } + + /// <summary> + /// Gets or sets the video profile. + /// </summary> + public VideoProfile VideoProfile { get; set; } + + /// <summary> + /// Gets or sets the video level. + /// </summary> + public VideoLevel VideoLevel { get; set; } + + /// <summary> + /// Gets or sets the video preset. + /// </summary> + public VideoPreset VideoPreset { get; set; } + + /// <summary> + /// Gets or sets the video tunes. + /// </summary> + public List<VideoTune> VideoTunes { get; set; } + + /// <summary> + /// Gets or sets Extra Advanced Arguments for the Video Tab. + /// </summary> + public string ExtraAdvancedArguments { get; set; } + + #endregion + + #region Preview + + /// <summary> + /// Gets or sets a value indicating whether IsPreviewEncode. + /// </summary> + public bool IsPreviewEncode { get; set; } + + /// <summary> + /// Gets or sets PreviewEncodeDuration. + /// </summary> + public int? PreviewEncodeDuration { get; set; } + + /// <summary> + /// Gets or sets PreviewEncodeStartAt. + /// </summary> + public int? PreviewEncodeStartAt { get; set; } + + #endregion + + #region Helpers + + /// <summary> + /// Gets a value indicating whether M4v extension is required. + /// </summary> + public bool RequiresM4v + { + get + { + if (this.OutputFormat == OutputFormat.Mp4) + { + bool audio = + this.AudioTracks.Any( + item => + item.Encoder == AudioEncoder.Ac3Passthrough || item.Encoder == AudioEncoder.Ac3 + || item.Encoder == AudioEncoder.DtsPassthrough || item.Encoder == AudioEncoder.Passthrough); + + bool subtitles = this.SubtitleTracks.Any(track => track.SubtitleType != SubtitleType.VobSub); + + return audio || subtitles; + } + + return false; + } + } + + /// <summary> + /// Gets or sets a value indicating whether advanced panel enabled. + /// </summary> + public bool ShowAdvancedTab + { + get + { + return this.showAdvancedTab; + } + set + { + if (!Equals(value, this.showAdvancedTab)) + { + this.showAdvancedTab = value; + this.NotifyOfPropertyChange(() => this.ShowAdvancedTab); + } + } + } + + /// <summary> + /// Gets the picture settings desc. + /// </summary> + public string PictureSettingsDesc + { + get + { + string resolution = string.Empty; + switch (this.Anamorphic) + { + case Anamorphic.Strict: + resolution = "Anamorphic: Strict"; + break; + case Anamorphic.Loose: + resolution = "Anamorphic: Loose, Width: " + this.Width; + break; + case Anamorphic.Custom: + resolution = "Anamorphic: Custom, Resolution: " + this.Width + "x" + this.Height; + break; + case Anamorphic.None: + resolution = "Resolution: " + this.Width + "x" + this.Height; + break; + } + + return resolution + Environment.NewLine + "Crop Top: " + this.Cropping.Top + ", Botton: " + this.Cropping.Bottom + ", Left: " + + this.Cropping.Left + ", Right: " + this.Cropping.Right; + } + } + + #endregion + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AllowedPassthru.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AllowedPassthru.cs new file mode 100644 index 000000000..9586e1632 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AllowedPassthru.cs @@ -0,0 +1,172 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="AllowedPassthru.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> +// Allowed Passthru Options +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System.Collections.Generic; + + /// <summary> + /// Allowed Passthru Options + /// </summary> + public class AllowedPassthru + { + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="AllowedPassthru"/> class. + /// </summary> + public AllowedPassthru() + { + this.AudioAllowAACPass = true; + this.AudioAllowAC3Pass = true; + this.AudioAllowDTSHDPass = true; + this.AudioAllowDTSPass = true; + this.AudioAllowMP3Pass = true; + this.AudioAllowEAC3Pass = true; + this.AudioAllowTrueHDPass = true; + this.AudioAllowFlacPass = true; + this.AudioEncoderFallback = AudioEncoder.Ac3; + } + + /// <summary> + /// Initializes a new instance of the <see cref="AllowedPassthru"/> class. + /// </summary> + /// <param name="initialValue"> + /// The initial Value. + /// </param> + public AllowedPassthru(bool initialValue) + { + this.AudioAllowAACPass = initialValue; + this.AudioAllowAC3Pass = initialValue; + this.AudioAllowDTSHDPass = initialValue; + this.AudioAllowDTSPass = initialValue; + this.AudioAllowMP3Pass = initialValue; + this.AudioAllowEAC3Pass = initialValue; + this.AudioAllowTrueHDPass = initialValue; + this.AudioAllowFlacPass = initialValue; + this.AudioEncoderFallback = AudioEncoder.Ac3; + } + + /// <summary> + /// Initializes a new instance of the <see cref="AllowedPassthru"/> class. + /// Copy Constructor + /// </summary> + /// <param name="initialValue"> + /// The initial value. + /// </param> + public AllowedPassthru(AllowedPassthru initialValue) + { + this.AudioAllowAACPass = initialValue.AudioAllowAACPass; + this.AudioAllowAC3Pass = initialValue.AudioAllowAC3Pass; + this.AudioAllowDTSHDPass = initialValue.AudioAllowDTSHDPass; + this.AudioAllowDTSPass = initialValue.AudioAllowDTSPass; + this.AudioAllowMP3Pass = initialValue.AudioAllowMP3Pass; + this.AudioAllowEAC3Pass = initialValue.AudioAllowEAC3Pass; + this.AudioAllowTrueHDPass = initialValue.AudioAllowTrueHDPass; + this.AudioAllowFlacPass = initialValue.AudioAllowFlacPass; + this.AudioEncoderFallback = initialValue.AudioEncoderFallback; + } + + #endregion + + #region Properties + + /// <summary> + /// Gets or sets a value indicating whether AudioAllowAACPass. + /// </summary> + public bool AudioAllowAACPass { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether AudioAllowAC3Pass. + /// </summary> + public bool AudioAllowAC3Pass { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether AudioAllowDTSHDPass. + /// </summary> + public bool AudioAllowDTSHDPass { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether AudioAllowDTSPass. + /// </summary> + public bool AudioAllowDTSPass { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether AudioAllowMP3Pass. + /// </summary> + public bool AudioAllowMP3Pass { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether audio allow true hd pass. + /// </summary> + public bool AudioAllowTrueHDPass { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether audio allow flac pass. + /// </summary> + public bool AudioAllowFlacPass { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether audio allow ea c 3 pass. + /// </summary> + public bool AudioAllowEAC3Pass { get; set; } + + /// <summary> + /// Gets or sets AudioEncoderFallback. + /// </summary> + public AudioEncoder AudioEncoderFallback { get; set; } + + /// <summary> + /// Gets the allowed passthru options. + /// </summary> + public IEnumerable<AudioEncoder> AllowedPassthruOptions + { + get + { + List<AudioEncoder> audioEncoders = new List<AudioEncoder>(); + if (this.AudioAllowAACPass) + { + audioEncoders.Add(AudioEncoder.AacPassthru); + } + if (this.AudioAllowAC3Pass) + { + audioEncoders.Add(AudioEncoder.Ac3Passthrough); + } + if (this.AudioAllowDTSHDPass) + { + audioEncoders.Add(AudioEncoder.DtsHDPassthrough); + } + if (this.AudioAllowDTSPass) + { + audioEncoders.Add(AudioEncoder.DtsPassthrough); + } + if (this.AudioAllowMP3Pass) + { + audioEncoders.Add(AudioEncoder.Mp3Passthru); + } + if (this.AudioAllowTrueHDPass) + { + audioEncoders.Add(AudioEncoder.TrueHDPassthrough); + } + if (this.AudioAllowFlacPass) + { + audioEncoders.Add(AudioEncoder.FlacPassthru); + } + if (this.AudioAllowEAC3Pass) + { + audioEncoders.Add(AudioEncoder.EAc3Passthrough); + } + + return audioEncoders; + } + } + + #endregion + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AudioEncoder.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AudioEncoder.cs new file mode 100644 index 000000000..fe56a1e14 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AudioEncoder.cs @@ -0,0 +1,89 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="AudioEncoder.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> +// The audio encoder enumeration +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System.ComponentModel.DataAnnotations; + + using HandBrake.ApplicationServices.Attributes; + + /// <summary> + /// The audio encoder. + /// </summary> + public enum AudioEncoder + { + [Display(Name = "AAC (avcodec)")] + [ShortName("av_aac")] + ffaac, + + [Display(Name = "AAC (FDK)")] + [ShortName("fdk_aac")] + fdkaac, + + [Display(Name = "HE-AAC (FDK)")] + [ShortName("fdk_haac")] + fdkheaac, + + [Display(Name = "MP3")] + [ShortName("mp3")] + Lame, + + [Display(Name = "AC3")] + [ShortName("ac3")] + Ac3, + + [Display(Name = "Auto Passthru")] + [ShortName("copy")] + Passthrough, + + [Display(Name = "AC3 Passthru")] + [ShortName("copy:ac3")] + Ac3Passthrough, + + [Display(Name = "E-AC3 Passthru")] + [ShortName("copy:eac3")] + EAc3Passthrough, + + [Display(Name = "DTS Passthru")] + [ShortName("copy:dts")] + DtsPassthrough, + + [Display(Name = "DTS-HD Passthru")] + [ShortName("copy:dtshd")] + DtsHDPassthrough, + + [Display(Name = "TrueHD Passthru")] + [ShortName("copy:truehd")] + TrueHDPassthrough, + + [Display(Name = "AAC Passthru")] + [ShortName("copy:aac")] + AacPassthru, + + [Display(Name = "MP3 Passthru")] + [ShortName("copy:mp3")] + Mp3Passthru, + + [Display(Name = "Vorbis")] + [ShortName("vorbis")] + Vorbis, + + [Display(Name = "FLAC 16-bit")] + [ShortName("flac16")] + ffflac, + + [Display(Name = "FLAC 24-bit")] + [ShortName("flac24")] + ffflac24, + + [Display(Name = "FLAC Passthru")] + [ShortName("copy:flac")] + FlacPassthru, + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AudioEncoderRateType.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AudioEncoderRateType.cs new file mode 100644 index 000000000..d1cd21e5b --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AudioEncoderRateType.cs @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="AudioEncoderRateType.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> +// The audio encoder rate type. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System.ComponentModel.DataAnnotations; + + /// <summary> + /// The audio encoder rate type. + /// </summary> + public enum AudioEncoderRateType + { + /// <summary> + /// The bitrate. + /// </summary> + [Display(Name = "Bitrate: ")] + Bitrate, + + /// <summary> + /// The quality. + /// </summary> + [Display(Name = "Quality: ")] + Quality, + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AudioTrack.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AudioTrack.cs new file mode 100644 index 000000000..c435e88ec --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/AudioTrack.cs @@ -0,0 +1,636 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="AudioTrack.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> +// Model of a HandBrake Audio Track and it's associated behaviours. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Globalization; + using System.Linq; + + using HandBrake.ApplicationServices.Interop; + using HandBrake.ApplicationServices.Interop.Model; + using HandBrake.ApplicationServices.Interop.Model.Encoding; + using HandBrake.ApplicationServices.Utilities; + + using HandBrakeWPF.Services.Scan.Model; + + using Newtonsoft.Json; + + /// <summary> + /// Model of a HandBrake Audio Track and it's associated behaviours. + /// </summary> + public class AudioTrack : PropertyChangedBase + { + private int bitrate; + private double drc; + private HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder encoder; + private int gain; + private Mixdown mixDown; + private double sampleRate; + [NonSerialized] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + private Audio scannedTrack; + private bool isDefault; + private IEnumerable<int> bitrates; + private IEnumerable<double> encoderQualityValues; + private HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType encoderRateType; + private double? quality; + + /// <summary> + /// Initializes a new instance of the <see cref = "AudioTrack" /> class. + /// </summary> + public AudioTrack() + { + // Default Values + this.Encoder = HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.ffaac; + this.MixDown = Mixdown.DolbyProLogicII; + this.SampleRate = 48; + this.Bitrate = 160; + this.DRC = 0; + this.ScannedTrack = new Audio(); + this.TrackName = string.Empty; + + // Setup Backing Properties + this.EncoderRateType = HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType.Bitrate; + this.SetupLimits(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="AudioTrack"/> class. + /// Copy Constructor + /// </summary> + /// <param name="track"> + /// The track. + /// </param> + /// <param name="setScannedTrack"> + /// The set Scanned Track. + /// </param> + public AudioTrack(AudioTrack track, bool setScannedTrack) + { + this.bitrate = track.Bitrate; + this.drc = track.DRC; + this.encoder = track.Encoder; + this.gain = track.Gain; + this.mixDown = track.MixDown; + this.sampleRate = track.SampleRate; + if (setScannedTrack) + { + this.scannedTrack = track.ScannedTrack ?? new Audio(); + } + this.TrackName = track.TrackName; + this.Quality = track.Quality; + + // Setup Backing Properties + this.encoderRateType = track.EncoderRateType; + this.SetupLimits(); + } + + #region Track Properties + + /// <summary> + /// Gets or sets Dynamic Range Compression + /// </summary> + public double DRC + { + get + { + return this.drc; + } + + set + { + if (!Equals(value, this.drc)) + { + this.drc = value; + this.NotifyOfPropertyChange(() => this.DRC); + } + } + } + + /// <summary> + /// Gets or sets the Gain for the audio track + /// </summary> + public int Gain + { + get + { + return this.gain; + } + + set + { + if (!Equals(value, this.gain)) + { + this.gain = value; + this.NotifyOfPropertyChange(() => this.Gain); + } + } + } + + /// <summary> + /// Gets or sets Audio Mixdown + /// </summary> + public Mixdown MixDown + { + get + { + return this.mixDown; + } + + set + { + this.mixDown = value; + this.NotifyOfPropertyChange(() => this.MixDown); + this.SetupLimits(); + this.NotifyOfPropertyChange(() => this.TrackReference); + } + } + + /// <summary> + /// Gets or sets Audio Encoder + /// </summary> + public HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder Encoder + { + get + { + return this.encoder; + } + + set + { + this.encoder = value; + this.NotifyOfPropertyChange(() => this.Encoder); + this.NotifyOfPropertyChange(() => this.IsPassthru); + this.NotifyOfPropertyChange(() => this.IsBitrateVisible); + this.NotifyOfPropertyChange(() => this.IsQualityVisible); + this.NotifyOfPropertyChange(() => this.IsRateTypeVisible); + this.SetupLimits(); + this.NotifyOfPropertyChange(() => this.TrackReference); + + // Refresh the available encoder rate types. + this.NotifyOfPropertyChange(() => this.AudioEncoderRateTypes); + if (!this.AudioEncoderRateTypes.Contains(this.EncoderRateType)) + { + this.EncoderRateType = HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType.Bitrate; // Default to bitrate. + } + } + } + + /// <summary> + /// Gets or sets Audio SampleRate + /// </summary> + public double SampleRate + { + get + { + return this.sampleRate; + } + + set + { + this.sampleRate = value; + this.NotifyOfPropertyChange(() => this.SampleRate); + this.SetupLimits(); + this.NotifyOfPropertyChange(() => this.TrackReference); + } + } + + /// <summary> + /// Gets or sets the encoder rate type. + /// </summary> + public HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType EncoderRateType + { + get + { + return this.encoderRateType; + } + + set + { + this.encoderRateType = value; + this.SetupLimits(); + this.NotifyOfPropertyChange(() => this.EncoderRateType); + this.NotifyOfPropertyChange(() => this.IsBitrateVisible); + this.NotifyOfPropertyChange(() => this.IsQualityVisible); + + if (!this.Quality.HasValue) + { + HBAudioEncoder hbAudioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder>.GetShortName(this.Encoder)); + this.Quality = HandBrakeEncoderHelpers.GetDefaultQuality(hbAudioEncoder); + } + } + } + + /// <summary> + /// Gets or sets Audio Bitrate + /// </summary> + public int Bitrate + { + get + { + return this.bitrate; + } + + set + { + this.bitrate = value; + this.NotifyOfPropertyChange(() => this.Bitrate); + } + } + + /// <summary> + /// Gets or sets Audio quality + /// </summary> + public double? Quality + { + get + { + return this.quality; + } + + set + { + this.quality = value; + this.NotifyOfPropertyChange(() => this.quality); + } + } + + /// <summary> + /// Gets or sets the track name. + /// </summary> + public string TrackName { get; set; } + #endregion + + /// <summary> + /// Gets AudioEncoderDisplayValue. + /// </summary> + [JsonIgnore] + public string AudioEncoderDisplayValue + { + get + { + return EnumHelper<HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder>.GetDisplay(this.Encoder); + } + } + + /// <summary> + /// Gets AudioMixdownDisplayValue. + /// </summary> + [JsonIgnore] + public string AudioMixdownDisplayValue + { + get + { + return EnumHelper<Mixdown>.GetDisplay(this.MixDown); + } + } + + /// <summary> + /// Gets the The UI display value for bit rate + /// </summary> + [JsonIgnore] + public string BitRateDisplayValue + { + get + { + if (this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.Ac3Passthrough || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.DtsPassthrough + || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.DtsHDPassthrough) + { + return "Auto"; + } + + return this.Bitrate.ToString(); + } + } + + /// <summary> + /// Gets or sets a value indicating whether is default. + /// TODO - Can this be removed? May have been added as a quick fix for a styling quirk. + /// </summary> + [JsonIgnore] + public bool IsDefault + { + get + { + return this.isDefault; + } + set + { + this.isDefault = value; + } + } + + /// <summary> + /// Gets or sets the The UI display value for sample rate + /// </summary> + [JsonIgnore] + public string SampleRateDisplayValue + { + get + { + return this.SampleRate == 0 ? "Auto" : this.SampleRate.ToString(CultureInfo.InvariantCulture); + } + set + { + // TODO change this to be a converted field + if (string.IsNullOrEmpty(value)) + { + return; + } + + double samplerate; + double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out samplerate); + + this.SampleRate = samplerate; + } + } + + /// <summary> + /// Gets or sets the Scanned Audio Tracks + /// </summary> + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Audio ScannedTrack + { + get + { + return this.scannedTrack; + } + + set + { + this.scannedTrack = value; + this.NotifyOfPropertyChange(() => this.ScannedTrack); + } + } + + /// <summary> + /// Gets the Audio Track Name + /// </summary> + [JsonIgnore] + public int? Track + { + get + { + if (this.ScannedTrack != null) + { + return this.ScannedTrack.TrackNumber; + } + + return null; + } + } + + /// <summary> + /// Gets a value indicating whether IsPassthru. + /// </summary> + [JsonIgnore] + public bool IsPassthru + { + get + { + if (this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.Ac3Passthrough || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.DtsPassthrough + || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.DtsHDPassthrough || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.AacPassthru + || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.Mp3Passthru || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.Passthrough || + this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.EAc3Passthrough || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.TrueHDPassthrough + || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.FlacPassthru) + { + return true; + } + return false; + } + } + + /// <summary> + /// Gets the bitrates. + /// </summary> + [JsonIgnore] + public IEnumerable<int> Bitrates + { + get + { + return this.bitrates; + } + } + + /// <summary> + /// Gets the quality compression values. + /// </summary> + [JsonIgnore] + public IEnumerable<double> EncoderQualityValues + { + get + { + return this.encoderQualityValues; + } + } + + /// <summary> + /// Gets the audio encoder rate types. + /// </summary> + [JsonIgnore] + public IEnumerable<HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType> AudioEncoderRateTypes + { + get + { + IList<HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType> types = EnumHelper<HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType>.GetEnumList().ToList(); + HBAudioEncoder hbaenc = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder>.GetShortName(this.Encoder)); + if (hbaenc == null || !hbaenc.SupportsQuality) + { + types.Remove(HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType.Quality); + } + + return types; + } + } + + /// <summary> + /// Gets a value indicating whether can set bitrate. + /// </summary> + [JsonIgnore] + public bool IsBitrateVisible + { + get + { + if (this.IsPassthru || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.ffflac || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.ffflac24) + { + return false; + } + + return Equals(this.EncoderRateType, HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType.Bitrate); + } + } + + /// <summary> + /// Gets a value indicating whether is quality visible. + /// </summary> + [JsonIgnore] + public bool IsQualityVisible + { + get + { + if (this.IsPassthru || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.ffflac || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.ffflac24) + { + return false; + } + + return Equals(this.EncoderRateType, HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType.Quality); + } + } + + /// <summary> + /// Gets a value indicating whether is rate type visible. + /// </summary> + [JsonIgnore] + public bool IsRateTypeVisible + { + get + { + if (this.IsPassthru || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.ffflac || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.ffflac24) + { + return false; + } + + return true; + } + } + + /// <summary> + /// Gets a value indicating whether IsLossless. + /// </summary> + [JsonIgnore] + public bool IsLossless + { + get + { + return this.IsPassthru || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.ffflac || this.Encoder == HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder.ffflac24; + } + } + + /// <summary> + /// Gets TrackReference. + /// </summary> + [JsonIgnore] + public AudioTrack TrackReference + { + get { return this; } + } + + #region Handler Methods + + /// <summary> + /// The setup limits. + /// </summary> + private void SetupLimits() + { + this.SetupBitrateLimits(); + this.SetupQualityCompressionLimits(); + } + + /// <summary> + /// The calculate bitrate limits. + /// </summary> + private void SetupBitrateLimits() + { + // Base set of bitrates available. + List<int> audioBitrates = HandBrakeEncoderHelpers.AudioBitrates; + + // Defaults + int max = 256; + int low = 32; + + // Based on the users settings, find the high and low bitrates. + HBAudioEncoder hbaenc = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder>.GetShortName(this.Encoder)); + HBRate rate = HandBrakeEncoderHelpers.AudioSampleRates.FirstOrDefault(t => t.Name == this.SampleRate.ToString(CultureInfo.InvariantCulture)); + HBMixdown mixdown = HandBrakeEncoderHelpers.GetMixdown(EnumHelper<Mixdown>.GetShortName(this.MixDown)); + + BitrateLimits limits = HandBrakeEncoderHelpers.GetBitrateLimits(hbaenc, rate != null ? rate.Rate : 48000, mixdown); + if (limits != null) + { + max = limits.High; + low = limits.Low; + } + + // Return the subset of available bitrates. + List<int> subsetBitrates = audioBitrates.Where(b => b <= max && b >= low).ToList(); + this.bitrates = subsetBitrates; + this.NotifyOfPropertyChange(() => this.Bitrates); + + // If the subset does not contain the current bitrate, request the default. + if (!subsetBitrates.Contains(this.Bitrate)) + { + this.Bitrate = HandBrakeEncoderHelpers.GetDefaultBitrate(hbaenc, rate != null ? rate.Rate : 48000, mixdown); + } + } + + /// <summary> + /// The setup quality compression limits. + /// </summary> + private void SetupQualityCompressionLimits() + { + HBAudioEncoder hbAudioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder>.GetShortName(this.Encoder)); + if (hbAudioEncoder.SupportsQuality) + { + RangeLimits limits = null; + + if (hbAudioEncoder.SupportsQuality) + { + limits = hbAudioEncoder.QualityLimits; + } + + if (limits != null) + { + double value = limits.Ascending ? limits.Low : limits.High; + List<double> values = new List<double> { value }; + + if (limits.Ascending) + { + while (value < limits.High) + { + value += limits.Granularity; + values.Add(value); + } + } + else + { + while (value > limits.Low) + { + value -= limits.Granularity; + values.Add(value); + } + } + + this.encoderQualityValues = values; + } + else + { + this.encoderQualityValues = new List<double>(); + } + } + else + { + this.encoderQualityValues = new List<double>(); + } + + // Default the audio quality value if it's out of range. + if (Equals(this.EncoderRateType, HandBrakeWPF.Services.Encode.Model.Models.AudioEncoderRateType.Quality)) + { + if (this.Quality.HasValue && !this.encoderQualityValues.Contains(this.Quality.Value)) + { + this.Quality = HandBrakeEncoderHelpers.GetDefaultQuality(hbAudioEncoder); + } + } + + this.NotifyOfPropertyChange(() => this.EncoderQualityValues); + } + + #endregion + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/ChapterMarker.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/ChapterMarker.cs new file mode 100644 index 000000000..da6979a4a --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/ChapterMarker.cs @@ -0,0 +1,92 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="ChapterMarker.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> +// A Movie Chapter +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System; + + using HandBrake.ApplicationServices.Utilities; + + /// <summary> + /// A Movie Chapter + /// </summary> + public class ChapterMarker : PropertyChangedBase + { + /// <summary> + /// Backing field for chapter name + /// </summary> + private string chapterName; + + /// <summary> + /// Initializes a new instance of the <see cref="ChapterMarker"/> class. + /// </summary> + public ChapterMarker() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="ChapterMarker"/> class. + /// </summary> + /// <param name="number"> + /// The number. + /// </param> + /// <param name="name"> + /// The name. + /// </param> + /// <param name="duration"> + /// The duration. + /// </param> + public ChapterMarker(int number, string name, TimeSpan duration) + { + this.ChapterName = name; + this.ChapterNumber = number; + this.Duration = duration; + } + + /// <summary> + /// Initializes a new instance of the <see cref="ChapterMarker"/> class. + /// Copy Constructor + /// </summary> + /// <param name="chapter"> + /// The chapter. + /// </param> + public ChapterMarker(ChapterMarker chapter) + { + this.ChapterName = chapter.ChapterName; + this.ChapterNumber = chapter.ChapterNumber; + this.Duration = chapter.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 the duration. + /// </summary> + public TimeSpan Duration { get; set; } + + /// <summary> + /// Gets or sets ChapterName. + /// </summary> + public string ChapterName + { + get + { + return this.chapterName; + } + set + { + this.chapterName = value; + this.NotifyOfPropertyChange(() => this.ChapterName); + } + } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/DenoisePreset.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/DenoisePreset.cs new file mode 100644 index 000000000..80ef02d7d --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/DenoisePreset.cs @@ -0,0 +1,45 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="DenoisePreset.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> +// Defines the DenoisePreset type. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System.ComponentModel.DataAnnotations; + + using HandBrake.ApplicationServices.Attributes; + + /// <summary> + /// The denoise preset. + /// </summary> + public enum DenoisePreset + { + [Display(Name = "Weak")] + [ShortName("weak")] + Weak = 0, + + [Display(Name = "Medium")] + [ShortName("medium")] + Medium, + + [Display(Name = "Strong")] + [ShortName("strong")] + Strong, + + [Display(Name = "Custom")] + [ShortName("custom")] + Custom, + + [Display(Name = "Ultralight")] // NLMeans only + [ShortName("ultralight")] + Ultralight, + + [Display(Name = "Light")] // NLMeans only + [ShortName("light")] + Light, + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/DenoiseTune.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/DenoiseTune.cs new file mode 100644 index 000000000..eb006ac3f --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/DenoiseTune.cs @@ -0,0 +1,41 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="DenoiseTune.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> +// Defines the DenoiseTune type. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System.ComponentModel.DataAnnotations; + + using HandBrake.ApplicationServices.Attributes; + + /// <summary> + /// The denoise tune. + /// </summary> + public enum DenoiseTune + { + [Display(Name = "None")] + [ShortName("none")] + None = 0, + + [Display(Name = "Film")] + [ShortName("film")] + Film, + + [Display(Name = "Grain")] + [ShortName("grain")] + Grain, + + [Display(Name = "High Motion")] + [ShortName("highmotion")] + HighMotion, + + [Display(Name = "Animation")] + [ShortName("animation")] + Animation, + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/FramerateMode.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/FramerateMode.cs new file mode 100644 index 000000000..d8eaa20fb --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/FramerateMode.cs @@ -0,0 +1,28 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="FramerateMode.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> +// The Mode of Video Encoding. CFR, VFR, PFR +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using HandBrake.ApplicationServices.Attributes; + + /// <summary> + /// The Mode of Video Encoding. CFR, VFR, PFR + /// </summary> + public enum FramerateMode + { + [ShortName("cfr")] + CFR = 0, + + [ShortName("pfr")] + PFR, + + [ShortName("vfr")] + VFR + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/OutputFormat.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/OutputFormat.cs new file mode 100644 index 000000000..d7e382b06 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/OutputFormat.cs @@ -0,0 +1,32 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="OutputFormat.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> +// The Output format. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System.ComponentModel; + using System.ComponentModel.DataAnnotations; + + using HandBrake.ApplicationServices.Attributes; + + /// <summary> + /// The Output format. + /// </summary> + public enum OutputFormat + { + [Description("MP4")] + [Display(Name = "MP4")] + [ShortName("av_mp4")] + Mp4 = 0, + + [Description("MKV")] + [Display(Name = "MKV")] + [ShortName("av_mkv")] + Mkv, + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/PointToPointMode.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/PointToPointMode.cs new file mode 100644 index 000000000..86f8d0133 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/PointToPointMode.cs @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PointToPointMode.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> +// Point to Point Mode +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System.ComponentModel.DataAnnotations; + + /// <summary> + /// Point to Point Mode + /// </summary> + public enum PointToPointMode + { + [Display(Name = "Chapters")] + Chapters = 0, + + [Display(Name = "Seconds")] + Seconds, + + [Display(Name = "Frames")] + Frames, + + [Display(Name = "Preview")] + Preview, + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/SubtitleTrack.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/SubtitleTrack.cs new file mode 100644 index 000000000..9f2ea9ded --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/SubtitleTrack.cs @@ -0,0 +1,275 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="SubtitleTrack.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> +// Subtitle Information +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System; + + using HandBrake.ApplicationServices.Utilities; + + using HandBrakeWPF.Services.Scan.Model; + + /// <summary> + /// Subtitle Information + /// </summary> + public class SubtitleTrack : PropertyChangedBase + { + #region Constants and Fields + + /// <summary> + /// The burned in backing field. + /// </summary> + private bool burned; + + /// <summary> + /// The is default backing field. + /// </summary> + private bool isDefault; + + /// <summary> + /// The source track. + /// </summary> + private Subtitle sourceTrack; + + /// <summary> + /// Backing field for the srt file name. + /// </summary> + private string srtFileName; + + /// <summary> + /// Backing field for Forced Subs + /// </summary> + private bool forced; + + #endregion + + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="SubtitleTrack"/> class. + /// </summary> + public SubtitleTrack() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="SubtitleTrack"/> class. + /// Copy Constructor + /// </summary> + /// <param name="subtitle"> + /// The subtitle. + /// </param> + public SubtitleTrack(SubtitleTrack subtitle) + { + this.Burned = subtitle.Burned; + this.Default = subtitle.Default; + this.Forced = subtitle.Forced; + this.sourceTrack = subtitle.SourceTrack; + this.SrtCharCode = subtitle.SrtCharCode; + this.SrtFileName = subtitle.SrtFileName; + this.SrtLang = subtitle.SrtLang; + this.SrtOffset = subtitle.SrtOffset; + this.SrtPath = subtitle.SrtPath; + this.SubtitleType = subtitle.SubtitleType; + this.SourceTrack = subtitle.SourceTrack; + } + + #endregion + + #region Properties + + /// <summary> + /// Gets or sets a value indicating whether Burned. + /// </summary> + public bool Burned + { + get + { + return this.burned; + } + + set + { + if (!Equals(this.burned, value)) + { + this.burned = value; + this.NotifyOfPropertyChange(() => this.Burned); + + if (value) + { + this.Default = false; + } + } + } + } + + /// <summary> + /// Gets or sets a value indicating whether Default. + /// </summary> + public bool Default + { + get + { + return this.isDefault; + } + + set + { + if (!Equals(this.isDefault, value)) + { + this.isDefault = value; + this.NotifyOfPropertyChange(() => this.Default); + + if (value) + { + this.Burned = false; + } + } + } + } + + /// <summary> + /// Gets or sets a value indicating whether Forced. + /// </summary> + public bool Forced + { + get + { + return this.forced; + } + set + { + this.forced = value; + this.NotifyOfPropertyChange(() => this.Forced); + } + } + + /// <summary> + /// Gets or sets SourceTrack. + /// </summary> + public Subtitle SourceTrack + { + get + { + return this.sourceTrack; + } + + set + { + this.sourceTrack = value; + this.NotifyOfPropertyChange(() => this.SourceTrack); + if (this.sourceTrack != null) + { + this.Track = this.sourceTrack.ToString(); + } + + this.NotifyOfPropertyChange(() => this.CanBeBurned); + this.NotifyOfPropertyChange(() => this.CanBeForced); + } + } + + /// <summary> + /// Gets or sets the SRT Character Code + /// </summary> + public string SrtCharCode { get; set; } + + /// <summary> + /// Gets or sets the SRT Filename + /// </summary> + public string SrtFileName + { + get + { + return this.srtFileName; + } + + set + { + this.srtFileName = value; + this.NotifyOfPropertyChange(() => this.IsSrtSubtitle); + } + } + + /// <summary> + /// Gets or sets the SRT Language + /// </summary> + public string SrtLang { get; set; } + + /// <summary> + /// Gets or sets the SRT Offset + /// </summary> + public int SrtOffset { get; set; } + + /// <summary> + /// Gets or sets the Path to the SRT file + /// </summary> + public string SrtPath { get; set; } + + /// <summary> + /// Gets or sets the type of the subtitle + /// </summary> + public SubtitleType SubtitleType { get; set; } + + /// <summary> + /// Gets or sets Track. + /// </summary> + [Obsolete("Use SourceTrack Instead")] + public string Track { get; set; } + + #endregion + + /// <summary> + /// Gets a value indicating whether CanForced. + /// </summary> + public bool CanBeForced + { + get + { + if (this.SourceTrack != null) + { + return this.SourceTrack.CanForce || this.SourceTrack.SubtitleType == SubtitleType.ForeignAudioSearch; + } + + return false; + } + } + + /// <summary> + /// Gets a value indicating whether CanBeBurned. + /// </summary> + public bool CanBeBurned + { + get + { + if (this.SourceTrack != null) + { + return this.SourceTrack.CanBurnIn || this.SourceTrack.SubtitleType == SubtitleType.ForeignAudioSearch || this.SubtitleType == SubtitleType.SRT; + } + + if (this.SubtitleType == SubtitleType.SRT) + { + return true; + } + + return false; + } + } + + /// <summary> + /// Gets a value indicating whether this is an SRT subtitle. + /// </summary> + public bool IsSrtSubtitle + { + get + { + return this.SrtFileName != "-" && this.SrtFileName != null; + } + } + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/SubtitleType.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/SubtitleType.cs new file mode 100644 index 000000000..85f9bf473 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/SubtitleType.cs @@ -0,0 +1,38 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="SubtitleType.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> +// Subtitle Type. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models +{ + using System.ComponentModel; + + /// <summary> + /// Subtitle Type. + /// </summary> + public enum SubtitleType + { + [Description("SSA")] + SSA, + [Description("SRT")] + SRT, + [Description("VobSub")] + VobSub, + [Description("CC")] + CC, + [Description("UTF8")] + UTF8Sub, + [Description("TX3G")] + TX3G, + [Description("PGS")] + PGS, + [Description("Unknown")] + Unknown, + [Description("Foreign Audio Search")] + ForeignAudioSearch, // Special Type for Foreign Audio Search + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoLevel.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoLevel.cs new file mode 100644 index 000000000..e7ca53e06 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoLevel.cs @@ -0,0 +1,118 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="VideoLevel.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> +// The video level. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models.Video +{ + using VideoLevelFactory = HandBrakeWPF.Services.Encode.Factories.VideoLevelFactory; + + /// <summary> + /// The video level. + /// </summary> + public class VideoLevel + { + /// <summary> + /// An internal representation of the Auto Selection. + /// </summary> + public static VideoLevel Auto = new VideoLevel("Auto", "auto"); + + /// <summary> + /// Initializes a new instance of the <see cref="VideoLevel"/> class. + /// </summary> + public VideoLevel() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="VideoLevel"/> class. + /// </summary> + /// <param name="displayName"> + /// The display name. + /// </param> + /// <param name="shortName"> + /// The short name. + /// </param> + public VideoLevel(string displayName, string shortName) + { + this.DisplayName = VideoLevelFactory.GetDisplayName(displayName); + this.ShortName = shortName; + } + + /// <summary> + /// Gets or sets the display name. + /// </summary> + public string DisplayName { get; set; } + + /// <summary> + /// Gets or sets the short name. + /// </summary> + public string ShortName { get; set; } + + /// <summary> + /// The clone. + /// </summary> + /// <returns> + /// The <see cref="VideoProfile"/>. + /// </returns> + public VideoLevel Clone() + { + return new VideoLevel(this.DisplayName, this.ShortName); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="other"> + /// The other. + /// </param> + /// <returns> + /// The <see cref="bool"/>. + /// </returns> + protected bool Equals(VideoLevel other) + { + return string.Equals(this.ShortName, other.ShortName); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="obj"> + /// The obj. + /// </param> + /// <returns> + /// The <see cref="bool"/>. + /// </returns> + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + if (ReferenceEquals(this, obj)) + { + return true; + } + if (obj.GetType() != this.GetType()) + { + return false; + } + return this.Equals((VideoLevel)obj); + } + + /// <summary> + /// The get hash code. + /// </summary> + /// <returns> + /// The <see cref="int"/>. + /// </returns> + public override int GetHashCode() + { + return (this.ShortName != null ? this.ShortName.GetHashCode() : 0); + } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoPreset.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoPreset.cs new file mode 100644 index 000000000..8efdf5b58 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoPreset.cs @@ -0,0 +1,121 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="VideoPreset.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> +// The video preset. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models.Video +{ + using VideoPresetFactory = HandBrakeWPF.Services.Encode.Factories.VideoPresetFactory; + + /// <summary> + /// The video preset. + /// </summary> + public class VideoPreset + { + /// <summary> + /// A built-in version of the "None" object. + /// </summary> + public static VideoPreset None = new VideoPreset("None", "none"); + + /// <summary> + /// Initializes a new instance of the <see cref="VideoPreset"/> class. + /// </summary> + public VideoPreset() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="VideoPreset"/> class. + /// </summary> + /// <param name="displayName"> + /// The display name. + /// </param> + /// <param name="shortName"> + /// The short name. + /// </param> + public VideoPreset(string displayName, string shortName) + { + this.DisplayName = VideoPresetFactory.GetDisplayName(displayName); + this.ShortName = shortName; + } + + /// <summary> + /// Gets or sets the display name. + /// </summary> + public string DisplayName { get; set; } + + /// <summary> + /// Gets or sets the short name. + /// </summary> + public string ShortName { get; set; } + + /// <summary> + /// The clone. + /// </summary> + /// <returns> + /// The <see cref="VideoProfile"/>. + /// </returns> + public VideoPreset Clone() + { + return new VideoPreset(this.DisplayName, this.ShortName); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="other"> + /// The other. + /// </param> + /// <returns> + /// The <see cref="bool"/>. + /// </returns> + protected bool Equals(VideoPreset other) + { + return string.Equals(this.ShortName, other.ShortName); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="obj"> + /// The obj. + /// </param> + /// <returns> + /// The <see cref="bool"/>. + /// </returns> + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != this.GetType()) + { + return false; + } + + return this.Equals((VideoPreset)obj); + } + + /// <summary> + /// The get hash code. + /// </summary> + /// <returns> + /// The <see cref="int"/>. + /// </returns> + public override int GetHashCode() + { + return (this.ShortName != null ? this.ShortName.GetHashCode() : 0); + } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoProfile.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoProfile.cs new file mode 100644 index 000000000..80d3fe26d --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoProfile.cs @@ -0,0 +1,121 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="VideoProfile.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> +// The video profile. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models.Video +{ + using VideoProfileFactory = HandBrakeWPF.Services.Encode.Factories.VideoProfileFactory; + + /// <summary> + /// The video profile. + /// </summary> + public class VideoProfile + { + /// <summary> + /// An internal representation of the Auto Selection. + /// </summary> + public static VideoProfile Auto = new VideoProfile("Auto", "auto"); + + /// <summary> + /// Initializes a new instance of the <see cref="VideoProfile"/> class. + /// </summary> + public VideoProfile() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="VideoProfile"/> class. + /// </summary> + /// <param name="displayName"> + /// The display name. + /// </param> + /// <param name="shortName"> + /// The short name. + /// </param> + public VideoProfile(string displayName, string shortName) + { + this.DisplayName = VideoProfileFactory.GetDisplayName(displayName); + this.ShortName = shortName; + } + + /// <summary> + /// Gets or sets the display name. + /// </summary> + public string DisplayName { get; set; } + + /// <summary> + /// Gets or sets the short name. + /// </summary> + public string ShortName { get; set; } + + /// <summary> + /// The clone. + /// </summary> + /// <returns> + /// The <see cref="VideoProfile"/>. + /// </returns> + public VideoProfile Clone() + { + return new VideoProfile(this.DisplayName, this.ShortName); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="other"> + /// The other. + /// </param> + /// <returns> + /// The <see cref="bool"/>. + /// </returns> + protected bool Equals(VideoProfile other) + { + return string.Equals(this.DisplayName, other.DisplayName) && string.Equals(this.ShortName, other.ShortName); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="obj"> + /// The obj. + /// </param> + /// <returns> + /// The <see cref="bool"/>. + /// </returns> + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + if (ReferenceEquals(this, obj)) + { + return true; + } + if (obj.GetType() != this.GetType()) + { + return false; + } + return this.Equals((VideoProfile)obj); + } + + /// <summary> + /// The get hash code. + /// </summary> + /// <returns> + /// The <see cref="int"/>. + /// </returns> + public override int GetHashCode() + { + unchecked + { + return ((this.DisplayName != null ? this.DisplayName.GetHashCode() : 0) * 397) ^ (this.ShortName != null ? this.ShortName.GetHashCode() : 0); + } + } + } +} diff --git a/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoTune.cs b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoTune.cs new file mode 100644 index 000000000..deba2a56f --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Encode/Model/Models/Video/VideoTune.cs @@ -0,0 +1,137 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="VideoTune.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> +// The video tune. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Encode.Model.Models.Video +{ + using VideoTuneFactory = HandBrakeWPF.Services.Encode.Factories.VideoTuneFactory; + + /// <summary> + /// The video tune. + /// </summary> + public class VideoTune + { + /// <summary> + /// Static object to represent "None" + /// </summary> + public static VideoTune None = new VideoTune("None", "none"); + + /// <summary> + /// Static object to represent "None" + /// </summary> + public static VideoTune FastDecode = new VideoTune("Fast Decode", "fastdecode"); + + /// <summary> + /// Initializes a new instance of the <see cref="VideoTune"/> class. + /// </summary> + public VideoTune() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="VideoTune"/> class. + /// </summary> + /// <param name="displayName"> + /// The display name. + /// </param> + /// <param name="shortName"> + /// The short name. + /// </param> + public VideoTune(string displayName, string shortName) + { + this.DisplayName = VideoTuneFactory.GetDisplayName(displayName); + this.ShortName = shortName; + } + + /// <summary> + /// Gets or sets the display name. + /// </summary> + public string DisplayName { get; set; } + + /// <summary> + /// Gets or sets the short name. + /// </summary> + public string ShortName { get; set; } + + /// <summary> + /// The clone. + /// </summary> + /// <returns> + /// The <see cref="HandBrakeWPF.Services.Encode.Model.Models.Video.VideoProfile"/>. + /// </returns> + public VideoTune Clone() + { + return new VideoTune(this.DisplayName, this.ShortName); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="other"> + /// The other. + /// </param> + /// <returns> + /// The <see cref="bool"/>. + /// </returns> + protected bool Equals(HandBrakeWPF.Services.Encode.Model.Models.Video.VideoProfile other) + { + return string.Equals(this.DisplayName, other.DisplayName) && string.Equals(this.ShortName, other.ShortName); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="other"> + /// The other. + /// </param> + /// <returns> + /// The <see cref="bool"/>. + /// </returns> + protected bool Equals(VideoTune other) + { + return string.Equals(this.ShortName, other.ShortName); + } + + /// <summary> + /// The equals. + /// </summary> + /// <param name="obj"> + /// The obj. + /// </param> + /// <returns> + /// The <see cref="bool"/>. + /// </returns> + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + if (ReferenceEquals(this, obj)) + { + return true; + } + if (obj.GetType() != this.GetType()) + { + return false; + } + return this.Equals((VideoTune)obj); + } + + /// <summary> + /// The get hash code. + /// </summary> + /// <returns> + /// The <see cref="int"/>. + /// </returns> + public override int GetHashCode() + { + return (this.ShortName != null ? this.ShortName.GetHashCode() : 0); + } + } +} diff --git a/win/CS/HandBrakeWPF/Services/PrePostActionService.cs b/win/CS/HandBrakeWPF/Services/PrePostActionService.cs index 45889207f..1d54d1e6f 100644 --- a/win/CS/HandBrakeWPF/Services/PrePostActionService.cs +++ b/win/CS/HandBrakeWPF/Services/PrePostActionService.cs @@ -15,7 +15,6 @@ namespace HandBrakeWPF.Services using Caliburn.Micro;
- using HandBrake.ApplicationServices.Services.Encode.EventArgs;
using HandBrake.ApplicationServices.Utilities;
using HandBrakeWPF.EventArgs;
@@ -23,6 +22,7 @@ namespace HandBrakeWPF.Services using HandBrakeWPF.Services.Queue.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
+ using EncodeCompletedEventArgs = HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs;
using Execute = Caliburn.Micro.Execute;
/// <summary>
diff --git a/win/CS/HandBrakeWPF/Services/Presets/Factories/JsonPresetFactory.cs b/win/CS/HandBrakeWPF/Services/Presets/Factories/JsonPresetFactory.cs index 7b50cb750..4be9cc038 100644 --- a/win/CS/HandBrakeWPF/Services/Presets/Factories/JsonPresetFactory.cs +++ b/win/CS/HandBrakeWPF/Services/Presets/Factories/JsonPresetFactory.cs @@ -18,9 +18,6 @@ namespace HandBrakeWPF.Services.Presets.Factories using HandBrake.ApplicationServices.Interop.Model;
using HandBrake.ApplicationServices.Interop.Model.Encoding;
using HandBrake.ApplicationServices.Model;
- using HandBrake.ApplicationServices.Services.Encode.Model;
- using HandBrake.ApplicationServices.Services.Encode.Model.Models;
- using HandBrake.ApplicationServices.Services.Encode.Model.Models.Video;
using HandBrake.ApplicationServices.Utilities;
using HandBrakeWPF.Model.Audio;
@@ -28,6 +25,18 @@ namespace HandBrakeWPF.Services.Presets.Factories using HandBrakeWPF.Model.Subtitles;
using HandBrakeWPF.Services.Presets.Model;
+ using AudioEncoder = HandBrakeWPF.Services.Encode.Model.Models.AudioEncoder;
+ using AudioTrack = HandBrakeWPF.Services.Encode.Model.Models.AudioTrack;
+ using DenoisePreset = HandBrakeWPF.Services.Encode.Model.Models.DenoisePreset;
+ using DenoiseTune = HandBrakeWPF.Services.Encode.Model.Models.DenoiseTune;
+ using EncodeTask = HandBrakeWPF.Services.Encode.Model.EncodeTask;
+ using FramerateMode = HandBrakeWPF.Services.Encode.Model.Models.FramerateMode;
+ using OutputFormat = HandBrakeWPF.Services.Encode.Model.Models.OutputFormat;
+ using VideoLevel = HandBrakeWPF.Services.Encode.Model.Models.Video.VideoLevel;
+ using VideoPreset = HandBrakeWPF.Services.Encode.Model.Models.Video.VideoPreset;
+ using VideoProfile = HandBrakeWPF.Services.Encode.Model.Models.Video.VideoProfile;
+ using VideoTune = HandBrakeWPF.Services.Encode.Model.Models.Video.VideoTune;
+
/// <summary>
/// The json preset factory.
/// </summary>
diff --git a/win/CS/HandBrakeWPF/Services/Presets/Model/Preset.cs b/win/CS/HandBrakeWPF/Services/Presets/Model/Preset.cs index 92aa27092..113e02e38 100644 --- a/win/CS/HandBrakeWPF/Services/Presets/Model/Preset.cs +++ b/win/CS/HandBrakeWPF/Services/Presets/Model/Preset.cs @@ -9,13 +9,10 @@ namespace HandBrakeWPF.Services.Presets.Model
{
- using Caliburn.Micro;
-
- using HandBrake.ApplicationServices.Services.Encode.Model;
-
using HandBrakeWPF.Model.Audio;
using HandBrakeWPF.Model.Subtitles;
+ using EncodeTask = HandBrakeWPF.Services.Encode.Model.EncodeTask;
using PresetPictureSettingsMode = HandBrakeWPF.Model.Picture.PresetPictureSettingsMode;
/// <summary>
diff --git a/win/CS/HandBrakeWPF/Services/Presets/PresetService.cs b/win/CS/HandBrakeWPF/Services/Presets/PresetService.cs index 9e1cba6ad..ce666f8aa 100644 --- a/win/CS/HandBrakeWPF/Services/Presets/PresetService.cs +++ b/win/CS/HandBrakeWPF/Services/Presets/PresetService.cs @@ -21,15 +21,12 @@ namespace HandBrakeWPF.Services.Presets using HandBrake.ApplicationServices.Exceptions;
using HandBrake.ApplicationServices.Interop;
using HandBrake.ApplicationServices.Interop.Json.Presets;
- using HandBrake.ApplicationServices.Interop.Model.Encoding;
using HandBrake.ApplicationServices.Model;
- using HandBrake.ApplicationServices.Services.Encode.Model.Models;
using HandBrake.ApplicationServices.Utilities;
- using HandBrakeWPF.Model.Audio;
using HandBrakeWPF.Model.Picture;
- using HandBrakeWPF.Model.Subtitles;
using HandBrakeWPF.Properties;
+ using HandBrakeWPF.Services.Encode.Model.Models;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.Services.Presets.Factories;
using HandBrakeWPF.Services.Presets.Interfaces;
diff --git a/win/CS/HandBrakeWPF/Services/Queue/Interfaces/IQueueProcessor.cs b/win/CS/HandBrakeWPF/Services/Queue/Interfaces/IQueueProcessor.cs index aaeb37708..7a27f685f 100644 --- a/win/CS/HandBrakeWPF/Services/Queue/Interfaces/IQueueProcessor.cs +++ b/win/CS/HandBrakeWPF/Services/Queue/Interfaces/IQueueProcessor.cs @@ -12,10 +12,10 @@ namespace HandBrakeWPF.Services.Queue.Interfaces using System;
using System.ComponentModel;
- using HandBrake.ApplicationServices.Services.Encode.Interfaces;
-
using HandBrakeWPF.Services.Queue.Model;
+ using IEncode = HandBrakeWPF.Services.Encode.Interfaces.IEncode;
+
/// <summary>
/// The Queue Processor
/// </summary>
diff --git a/win/CS/HandBrakeWPF/Services/Queue/Model/QueueTask.cs b/win/CS/HandBrakeWPF/Services/Queue/Model/QueueTask.cs index f11cb9b8d..79de64c24 100644 --- a/win/CS/HandBrakeWPF/Services/Queue/Model/QueueTask.cs +++ b/win/CS/HandBrakeWPF/Services/Queue/Model/QueueTask.cs @@ -10,9 +10,10 @@ namespace HandBrakeWPF.Services.Queue.Model
{
using HandBrake.ApplicationServices.Model;
- using HandBrake.ApplicationServices.Services.Encode.Model;
using HandBrake.ApplicationServices.Utilities;
+ using EncodeTask = HandBrakeWPF.Services.Encode.Model.EncodeTask;
+
/// <summary>
/// The QueueTask.
/// </summary>
diff --git a/win/CS/HandBrakeWPF/Services/Queue/QueueProcessor.cs b/win/CS/HandBrakeWPF/Services/Queue/QueueProcessor.cs index 15e05347b..4056633bb 100644 --- a/win/CS/HandBrakeWPF/Services/Queue/QueueProcessor.cs +++ b/win/CS/HandBrakeWPF/Services/Queue/QueueProcessor.cs @@ -18,13 +18,13 @@ namespace HandBrakeWPF.Services.Queue using HandBrake.ApplicationServices.Exceptions;
using HandBrake.ApplicationServices.Model;
- using HandBrake.ApplicationServices.Services.Encode.EventArgs;
- using HandBrake.ApplicationServices.Services.Encode.Interfaces;
using HandBrake.ApplicationServices.Utilities;
using HandBrakeWPF.Services.Queue.Model;
+ using EncodeCompletedEventArgs = HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs;
using Execute = Caliburn.Micro.Execute;
+ using IEncode = HandBrakeWPF.Services.Encode.Interfaces.IEncode;
using QueueCompletedEventArgs = HandBrakeWPF.EventArgs.QueueCompletedEventArgs;
using QueueProgressEventArgs = HandBrakeWPF.EventArgs.QueueProgressEventArgs;
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 |