summaryrefslogtreecommitdiffstats
path: root/win/CS/HandBrake.ApplicationServices
diff options
context:
space:
mode:
authorsr55 <[email protected]>2011-03-13 16:44:49 +0000
committersr55 <[email protected]>2011-03-13 16:44:49 +0000
commitb6a5d4eba610711d15ed99dc5f2e9e126ce06086 (patch)
treee72eb5be161c3ac9b01bbc3b3efcd4ab8f91e06c /win/CS/HandBrake.ApplicationServices
parent38f64c238720fe0524f99b380fbb1a8c795a7586 (diff)
Rename Direction C# to CS
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3846 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'win/CS/HandBrake.ApplicationServices')
-rw-r--r--win/CS/HandBrake.ApplicationServices/EventArgs/EncodeCompletedEventArgs.cs49
-rw-r--r--win/CS/HandBrake.ApplicationServices/EventArgs/EncodeProgressEventArgs.cs45
-rw-r--r--win/CS/HandBrake.ApplicationServices/EventArgs/QueueProgressEventArgs.cs33
-rw-r--r--win/CS/HandBrake.ApplicationServices/EventArgs/ScanCompletedEventArgs.cs49
-rw-r--r--win/CS/HandBrake.ApplicationServices/EventArgs/ScanProgressEventArgs.cs25
-rw-r--r--win/CS/HandBrake.ApplicationServices/Functions/Converters.cs189
-rw-r--r--win/CS/HandBrake.ApplicationServices/Functions/EnumHelper.cs35
-rw-r--r--win/CS/HandBrake.ApplicationServices/Functions/GrowlCommunicator.cs119
-rw-r--r--win/CS/HandBrake.ApplicationServices/Functions/PlistHelper.cs127
-rw-r--r--win/CS/HandBrake.ApplicationServices/Functions/System.cs56
-rw-r--r--win/CS/HandBrake.ApplicationServices/Functions/Win32.cs144
-rw-r--r--win/CS/HandBrake.ApplicationServices/Functions/Win7.cs73
-rw-r--r--win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj181
-rw-r--r--win/CS/HandBrake.ApplicationServices/Init.cs160
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/DriveInformation.cs44
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/EncodeTask.cs326
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/Anamorphic.cs24
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/AudioEncoder.cs33
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/AudioTrack.cs56
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/Cropping.cs63
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/Decomb.cs17
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/Deinterlace.cs20
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/Denoise.cs19
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/Detelecine.cs17
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/FramerateMode.cs17
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/Mixdown.cs33
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/OutputFormat.cs24
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/PointToPointMode.cs17
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/SubtitleTrack.cs95
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/SubtitleType.cs30
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/VideoEncodeRateMode.cs17
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Encoding/VideoEncoder.cs24
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/General/UpdateCheckInformation.cs53
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/General/UpdateCheckResult.cs71
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/Preset.cs64
-rw-r--r--win/CS/HandBrake.ApplicationServices/Model/QueueTask.cs84
-rw-r--r--win/CS/HandBrake.ApplicationServices/Parsing/AudioTrack.cs169
-rw-r--r--win/CS/HandBrake.ApplicationServices/Parsing/Chapter.cs126
-rw-r--r--win/CS/HandBrake.ApplicationServices/Parsing/Parser.cs163
-rw-r--r--win/CS/HandBrake.ApplicationServices/Parsing/Source.cs53
-rw-r--r--win/CS/HandBrake.ApplicationServices/Parsing/Subtitle.cs171
-rw-r--r--win/CS/HandBrake.ApplicationServices/Parsing/Title.cs234
-rw-r--r--win/CS/HandBrake.ApplicationServices/Properties/AssemblyInfo.cs.tmpl42
-rw-r--r--win/CS/HandBrake.ApplicationServices/Properties/Resources.Designer.cs70
-rw-r--r--win/CS/HandBrake.ApplicationServices/Properties/Resources.resx124
-rw-r--r--win/CS/HandBrake.ApplicationServices/Resources/logo64.pngbin0 -> 11967 bytes
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/Encode.cs595
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/Interfaces/IEncode.cs96
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/Interfaces/IPresetService.cs93
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueManager.cs113
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueProcessor.cs51
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/Interfaces/IScan.cs83
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/LibScan.cs328
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/PresetService.cs403
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/QueueManager.cs340
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs279
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/ScanService.cs355
-rw-r--r--win/CS/HandBrake.ApplicationServices/Services/UpdateService.cs97
-rw-r--r--win/CS/HandBrake.ApplicationServices/Settings.StyleCop14
-rw-r--r--win/CS/HandBrake.ApplicationServices/Utilities/AppcastReader.cs119
-rw-r--r--win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs664
-rw-r--r--win/CS/HandBrake.ApplicationServices/Utilities/QueryParserUtility.cs415
-rw-r--r--win/CS/HandBrake.ApplicationServices/Utilities/UtilityService.cs131
-rw-r--r--win/CS/HandBrake.ApplicationServices/app.config8
64 files changed, 7769 insertions, 0 deletions
diff --git a/win/CS/HandBrake.ApplicationServices/EventArgs/EncodeCompletedEventArgs.cs b/win/CS/HandBrake.ApplicationServices/EventArgs/EncodeCompletedEventArgs.cs
new file mode 100644
index 000000000..2d613f6d5
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/EventArgs/EncodeCompletedEventArgs.cs
@@ -0,0 +1,49 @@
+/* EncodeCompletedEventArgs.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.EventArgs
+{
+ using System;
+
+ /// <summary>
+ /// Encode Progress Event Args
+ /// </summary>
+ 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>
+ public EncodeCompletedEventArgs(bool sucessful, Exception exception, string errorInformation)
+ {
+ this.Successful = sucessful;
+ this.Exception = exception;
+ this.ErrorInformation = errorInformation;
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether Successful.
+ /// </summary>
+ public bool Successful { get; set; }
+
+ /// <summary>
+ /// Gets or sets Exception.
+ /// </summary>
+ public Exception Exception { get; set; }
+
+ /// <summary>
+ /// Gets or sets ErrorInformation.
+ /// </summary>
+ public string ErrorInformation { get; set; }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/EventArgs/EncodeProgressEventArgs.cs b/win/CS/HandBrake.ApplicationServices/EventArgs/EncodeProgressEventArgs.cs
new file mode 100644
index 000000000..b4d6b9a64
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/EventArgs/EncodeProgressEventArgs.cs
@@ -0,0 +1,45 @@
+/* EncodeProgressEventArgs.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.EventArgs
+{
+ using System;
+
+ /// <summary>
+ /// Encode Progress Event Args
+ /// </summary>
+ public class EncodeProgressEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Gets or sets PercentComplete.
+ /// </summary>
+ public float PercentComplete { get; set; }
+
+ /// <summary>
+ /// Gets or sets CurrentFrameRate.
+ /// </summary>
+ public float CurrentFrameRate { get; set; }
+
+ /// <summary>
+ /// Gets or sets AverageFrameRate.
+ /// </summary>
+ public float AverageFrameRate { get; set; }
+
+ /// <summary>
+ /// Gets or sets EstimatedTimeLeft.
+ /// </summary>
+ public TimeSpan EstimatedTimeLeft { get; set; }
+
+ /// <summary>
+ /// Gets or sets Task.
+ /// </summary>
+ public int Task { get; set; }
+
+ /// <summary>
+ /// Gets or sets TaskCount.
+ /// </summary>
+ public int TaskCount { get; set; }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/EventArgs/QueueProgressEventArgs.cs b/win/CS/HandBrake.ApplicationServices/EventArgs/QueueProgressEventArgs.cs
new file mode 100644
index 000000000..8613187bc
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/EventArgs/QueueProgressEventArgs.cs
@@ -0,0 +1,33 @@
+/* QueueProgressEventArgs.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.EventArgs
+{
+ using System;
+
+ using HandBrake.ApplicationServices.Model;
+
+ /// <summary>
+ /// Queue Progress Event Args
+ /// </summary>
+ public class QueueProgressEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="QueueProgressEventArgs"/> class.
+ /// </summary>
+ /// <param name="newJob">
+ /// The new job.
+ /// </param>
+ public QueueProgressEventArgs(QueueTask newJob)
+ {
+ this.NewJob = newJob;
+ }
+
+ /// <summary>
+ /// Gets or sets the new job which is about to be processed.
+ /// </summary>
+ public QueueTask NewJob { get; set; }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/EventArgs/ScanCompletedEventArgs.cs b/win/CS/HandBrake.ApplicationServices/EventArgs/ScanCompletedEventArgs.cs
new file mode 100644
index 000000000..9b0437ac7
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/EventArgs/ScanCompletedEventArgs.cs
@@ -0,0 +1,49 @@
+/* ScanCompletedEventArgs.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.EventArgs
+{
+ using System;
+
+ /// <summary>
+ /// Scan Progress Event Args
+ /// </summary>
+ public class ScanCompletedEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ScanCompletedEventArgs"/> class.
+ /// </summary>
+ /// <param name="sucessful">
+ /// The sucessful.
+ /// </param>
+ /// <param name="exception">
+ /// The exception.
+ /// </param>
+ /// <param name="errorInformation">
+ /// The error information.
+ /// </param>
+ public ScanCompletedEventArgs(bool sucessful, Exception exception, string errorInformation)
+ {
+ this.Successful = sucessful;
+ this.Exception = exception;
+ this.ErrorInformation = errorInformation;
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether Successful.
+ /// </summary>
+ public bool Successful { get; set; }
+
+ /// <summary>
+ /// Gets or sets Exception.
+ /// </summary>
+ public Exception Exception { get; set; }
+
+ /// <summary>
+ /// Gets or sets ErrorInformation.
+ /// </summary>
+ public string ErrorInformation { get; set; }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/EventArgs/ScanProgressEventArgs.cs b/win/CS/HandBrake.ApplicationServices/EventArgs/ScanProgressEventArgs.cs
new file mode 100644
index 000000000..1a6bdb0a1
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/EventArgs/ScanProgressEventArgs.cs
@@ -0,0 +1,25 @@
+/* ScanProgressEventArgs.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.EventArgs
+{
+ using System;
+
+ /// <summary>
+ /// Scan Progress Event Args
+ /// </summary>
+ public class ScanProgressEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Gets or sets the title currently being scanned.
+ /// </summary>
+ public int CurrentTitle { get; set; }
+
+ /// <summary>
+ /// Gets or sets the total number of Titles.
+ /// </summary>
+ public int Titles { get; set; }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Functions/Converters.cs b/win/CS/HandBrake.ApplicationServices/Functions/Converters.cs
new file mode 100644
index 000000000..1dd817e23
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Functions/Converters.cs
@@ -0,0 +1,189 @@
+/* Converters.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Functions
+{
+ using System;
+ using System.Text.RegularExpressions;
+
+ using HandBrake.ApplicationServices.Model.Encoding;
+
+ /// <summary>
+ /// A class to convert various things to native C# objects
+ /// </summary>
+ public class Converters
+ {
+ /**
+ * TODO:
+ * - Many of these converters can be ditched at a later point. Should be able to model all this within the enums themsevles.
+ *
+ **/
+
+ /// <summary>
+ /// Convert HandBrakes time remaining into a TimeSpan
+ /// </summary>
+ /// <param name="time">
+ /// The time remaining for the encode.
+ /// </param>
+ /// <returns>
+ /// A TimepSpan object
+ /// </returns>
+ public static TimeSpan EncodeToTimespan(string time)
+ {
+ TimeSpan converted = new TimeSpan(0, 0, 0, 0);
+
+ Match m = Regex.Match(time.Trim(), @"^([0-9]{2}:[0-9]{2}:[0-9]{2})");
+ if (m.Success)
+ {
+ TimeSpan.TryParse(m.Groups[0].Value, out converted);
+ }
+
+ return converted;
+ }
+
+ /// <summary>
+ /// Get the GUI equiv to a CLI mixdown
+ /// </summary>
+ /// <param name="mixdown">The Audio Mixdown</param>
+ /// <returns>The GUI representation of the mixdown</returns>
+ public static string GetMixDown(string mixdown)
+ {
+ switch (mixdown.Trim())
+ {
+ case "mono":
+ return "Mono";
+ case "stereo":
+ return "Stereo";
+ case "dpl1":
+ return "Dolby Surround";
+ case "dpl2":
+ return "Dolby Pro Logic II";
+ case "6ch":
+ return "6 Channel Discrete";
+ default:
+ return "Automatic";
+ }
+ }
+
+ /// <summary>
+ /// Get the GUI equiv to a CLI audio encoder
+ /// </summary>
+ /// <param name="audioEnc">The Audio Encoder</param>
+ /// <returns>The GUI representation of that audio encoder</returns>
+ public static string GetGUIAudioEncoder(string audioEnc)
+ {
+ switch (audioEnc)
+ {
+ case "faac":
+ return "AAC (faac)";
+ case "lame":
+ return "MP3 (lame)";
+ case "vorbis":
+ return "Vorbis (vorbis)";
+ case "ac3":
+ return "AC3 (ffmpeg)";
+ case "copy:ac3":
+ return "AC3 Passthru";
+ case "copy:dts":
+ return "DTS Passthru";
+ default:
+ return "AAC (faac)";
+ }
+ }
+
+ /// <summary>
+ /// Get the Video Encoder for a given string
+ /// </summary>
+ /// <param name="encoder">
+ /// The encoder name
+ /// </param>
+ /// <returns>
+ /// VideoEncoder enum object
+ /// </returns>
+ public static VideoEncoder GetVideoEncoder(string encoder)
+ {
+ switch (encoder)
+ {
+ case "ffmpeg":
+ return VideoEncoder.FFMpeg;
+ case "x264":
+ return VideoEncoder.X264;
+ case "theora":
+ return VideoEncoder.Theora;
+ default:
+ return VideoEncoder.X264;
+ }
+ }
+
+ /// <summary>
+ /// Get a GUI name for a given video Encoder.
+ /// </summary>
+ /// <param name="encoder">
+ /// A VideoEncoder Enum object
+ /// </param>
+ /// <returns>
+ /// A GUI encoder name, default is x264
+ /// </returns>
+ public static string GetGUIVideoEncoder(VideoEncoder encoder)
+ {
+ switch (encoder)
+ {
+ case VideoEncoder.FFMpeg:
+ return "MPEG-4 (FFmpeg)";
+ case VideoEncoder.X264:
+ return "H.264 (x264)";
+ case VideoEncoder.Theora:
+ return "VP3 (Theora)";
+ default:
+ return "H.264 (x264)";
+ }
+ }
+
+
+ /// <summary>
+ /// Get the OutputFormat Enum for a given string
+ /// </summary>
+ /// <param name="format">
+ /// OutputFormat as a string
+ /// </param>
+ /// <returns>
+ /// An OutputFormat Enum
+ /// </returns>
+ public static OutputFormat GetFileFormat(string format)
+ {
+ switch (format.ToLower())
+ {
+ default:
+ return OutputFormat.Mp4;
+ case "m4v":
+ return OutputFormat.M4V;
+ case "mkv":
+ return OutputFormat.Mkv;
+ }
+ }
+
+ /// <summary>
+ /// Get the OutputFormat Enum for a given string
+ /// </summary>
+ /// <param name="format">
+ /// OutputFormat as a string
+ /// </param>
+ /// <returns>
+ /// An OutputFormat Enum
+ /// </returns>
+ public static string GetFileFormat(OutputFormat format)
+ {
+ switch (format)
+ {
+ default:
+ return "mp4";
+ case OutputFormat.M4V:
+ return "m4v";
+ case OutputFormat.Mkv:
+ return "mkv";
+ }
+ }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Functions/EnumHelper.cs b/win/CS/HandBrake.ApplicationServices/Functions/EnumHelper.cs
new file mode 100644
index 000000000..0bbc746d7
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Functions/EnumHelper.cs
@@ -0,0 +1,35 @@
+/* EnumHelper.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Functions
+{
+ using System;
+ using System.ComponentModel;
+ using System.Reflection;
+
+ /// <summary>
+ /// Enum Helpers
+ /// </summary>
+ public class EnumHelper
+ {
+ /// <summary>
+ /// Get the description of an Enum
+ /// </summary>
+ /// <param name="value">
+ /// The value.
+ /// </param>
+ /// <returns>
+ /// The Description string
+ /// </returns>
+ public static string GetDescription(Enum value)
+ {
+ FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
+ DescriptionAttribute[] attributes =
+ (DescriptionAttribute[])fieldInfo.GetCustomAttributes(
+ typeof(DescriptionAttribute), false);
+ return (attributes.Length > 0) ? attributes[0].Description : value.ToString();
+ }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Functions/GrowlCommunicator.cs b/win/CS/HandBrake.ApplicationServices/Functions/GrowlCommunicator.cs
new file mode 100644
index 000000000..a28457836
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Functions/GrowlCommunicator.cs
@@ -0,0 +1,119 @@
+/* GrowlCommunicator.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Functions
+{
+ using System;
+
+ using Growl.Connector;
+
+ /// <summary>
+ /// Provides all functionality for communicating with Growl for Windows.
+ /// </summary>
+ /// <remarks>
+ /// This class is implemented as a static class because:
+ /// 1. It allows nearly all of the Growl-related code to be in one place
+ /// 2. It prevents the main form, queue handler, and any other part of Handbrake from having to declare
+ /// or track any new instance variables
+ /// </remarks>
+ public static class GrowlCommunicator
+ {
+ /// <summary>
+ /// The <see cref="GrowlConnector"/> that actually talks to Growl
+ /// </summary>
+ private static GrowlConnector growl;
+
+ /// <summary>
+ /// The Handbrake application instance that is registered with Growl
+ /// </summary>
+ private static Application application;
+
+ /// <summary>
+ /// Notification shown upon completion of encoding
+ /// </summary>
+ private static NotificationType encodeOrQueueCompleted = new NotificationType("EncodeOrQueue", "HandBrake Status");
+
+ /// <summary>
+ /// Checks to see if Growl is currently running on the local machine.
+ /// </summary>
+ /// <returns>
+ /// <c>true</c> if Growl is running;
+ /// <c>false</c> otherwise
+ /// </returns>
+ public static bool IsRunning()
+ {
+ Initialize();
+
+ return GrowlConnector.IsGrowlRunningLocally();
+ }
+
+ /// <summary>
+ /// Registers Handbrake with the local Growl instance
+ /// </summary>
+ /// <remarks>
+ /// This should usually be called at application start-up
+ /// </remarks>
+ public static void Register()
+ {
+ Initialize();
+ growl.Register(application, new[] {encodeOrQueueCompleted});
+ }
+
+ /// <summary>
+ /// Sends a notification to Growl. (Since Handbrake currently only supports one type of notification with
+ /// static text, this is a shortcut method).
+ /// </summary>
+ /// <param name="title">
+ /// The title.
+ /// </param>
+ /// <param name="text">
+ /// The text to display.
+ /// </param>
+ public static void Notify(string title, string text)
+ {
+ Notification notification = new Notification(application.Name, encodeOrQueueCompleted.Name, String.Empty,
+ title, text);
+ growl.Notify(notification);
+ }
+
+ /// <summary>
+ /// Sends a notification to Growl. (This is the more generic version that could be used in the future if
+ /// more notification types are implemented)
+ /// </summary>
+ /// <param name="notificationType">The <see cref="NotificationType">type</see> of notification to send</param>
+ /// <param name="title">The notification title</param>
+ /// <param name="text">The notification text</param>
+ /// <param name="imageUrl">The notification image as a url</param>
+ public static void Notify(NotificationType notificationType, string title, string text, string imageUrl)
+ {
+ Notification notification = new Notification(application.Name, notificationType.Name, String.Empty, title,
+ text)
+ {
+ Icon = imageUrl
+ };
+
+ growl.Notify(notification);
+ }
+
+ /// <summary>
+ /// Initializes the GrowlCommunicator
+ /// </summary>
+ private static void Initialize()
+ {
+ if (growl == null)
+ {
+ growl = new GrowlConnector
+ {
+ EncryptionAlgorithm = Cryptography.SymmetricAlgorithmType.PlainText
+ };
+
+ application = new Application("Handbrake")
+ {
+ Icon = Properties.Resources.logo64
+ };
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Functions/PlistHelper.cs b/win/CS/HandBrake.ApplicationServices/Functions/PlistHelper.cs
new file mode 100644
index 000000000..fab40a27c
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Functions/PlistHelper.cs
@@ -0,0 +1,127 @@
+/* PlistHelper.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+
+namespace HandBrake.ApplicationServices.Functions
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Xml;
+
+ /// <summary>
+ /// A Plist Helper
+ /// </summary>
+ public class PlistHelper
+ {
+ /// <summary>
+ /// Get the Audio Track XML Nodes from a plist preset file
+ /// </summary>
+ /// <param name="filename">
+ /// A Plist preset file
+ /// </param>
+ /// <returns>
+ /// A List of XmlNodes which contain audio tracks
+ /// </returns>
+ public static List<XmlNode> GetAudioTracks(string filename)
+ {
+ // Data Store
+ List<XmlNode> audioTracks = new List<XmlNode>();
+
+ // Load the file and get the Root note, or return if none found
+ XmlNode root = LoadFile(filename);
+ if (root == null)
+ {
+ return null;
+ }
+
+ // Get the Audio Tracks
+ XmlNode audioListDict = root.ChildNodes[2].ChildNodes[0].FirstChild.ChildNodes[1];
+ for (int i = 0; i < audioListDict.ChildNodes.Count; i++)
+ {
+ XmlNode audioChannel = audioListDict.ChildNodes[i]; // <dict>
+ audioTracks.Add(audioChannel);
+ }
+
+ return audioTracks;
+ }
+
+ /// <summary>
+ /// Get the settings portion of a presets file
+ /// </summary>
+ /// <param name="filename">
+ /// A Plist preset file
+ /// </param>
+ /// <returns>
+ /// A Dictionary of plist key against an XML node containing the setting.
+ /// </returns>
+ public static Dictionary<string, XmlNode> GetPresetSettings(string filename)
+ {
+ // Data Store
+ Dictionary<string, XmlNode> settings = new Dictionary<string, XmlNode>();
+
+ // Load the file and get the Root note, or return if none found
+ XmlNode root = LoadFile(filename);
+ if (root == null)
+ {
+ return null;
+ }
+
+ // Get the Preset Settings, starting from the 3rd node (skipping the audio notes we've just prcessed)
+ XmlNode presetSettings = root.ChildNodes[2].ChildNodes[0].FirstChild;
+ for (int i = 2; i < presetSettings.ChildNodes.Count; i += 2)
+ {
+ string key = presetSettings.ChildNodes[i].InnerText;
+ XmlNode node = presetSettings.ChildNodes[i + 1];
+ settings.Add(key, node);
+ }
+
+ return settings;
+ }
+
+ /// <summary>
+ /// Load a Plist Preset file and return it as an XML document
+ /// </summary>
+ /// <param name="filename">
+ /// A Plist preset file
+ /// </param>
+ /// <returns>
+ /// An XML document
+ /// </returns>
+ private static XmlNode LoadFile(string filename)
+ {
+ try
+ {
+ if (!File.Exists(filename))
+ {
+ return null;
+ }
+
+ StreamReader sr = File.OpenText(filename);
+ string fromfile = string.Empty;
+ int fileChar;
+ while ((fileChar = sr.Read()) != -1)
+ {
+ fromfile += Convert.ToChar(fileChar);
+ }
+
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(fromfile);
+
+ XmlNode root = doc;
+ if (!root.HasChildNodes)
+ {
+ return null;
+ }
+
+ return root;
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Functions/System.cs b/win/CS/HandBrake.ApplicationServices/Functions/System.cs
new file mode 100644
index 000000000..9b08a4be2
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Functions/System.cs
@@ -0,0 +1,56 @@
+/* System.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Functions
+{
+ using System.Windows.Forms;
+
+ using Microsoft.Win32;
+
+ /// <summary>
+ /// The System Information.
+ /// </summary>
+ public class SystemInfo
+ {
+ /// <summary>
+ /// Gets the total physical ram in a system
+ /// </summary>
+ /// <returns>The total memory in the system</returns>
+ public static ulong TotalPhysicalMemory
+ {
+ get
+ {
+ Win32.MEMORYSTATUSEX memStat = new Win32.MEMORYSTATUSEX { dwLength = 64 };
+ Win32.GlobalMemoryStatusEx(ref memStat);
+
+ ulong value = memStat.ullTotalPhys / 1024 / 1024;
+ return value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of CPU Cores
+ /// </summary>
+ /// <returns>Object</returns>
+ public static object GetCpuCount
+ {
+ get
+ {
+ RegistryKey regKey = Registry.LocalMachine;
+ regKey = regKey.OpenSubKey("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
+ return regKey == null ? 0 : regKey.GetValue("ProcessorNameString");
+ }
+ }
+
+ /// <summary>
+ /// Gets the System screen size information.
+ /// </summary>
+ /// <returns>System.Windows.Forms.Scree</returns>
+ public static Screen ScreenBounds
+ {
+ get { return Screen.PrimaryScreen; }
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Functions/Win32.cs b/win/CS/HandBrake.ApplicationServices/Functions/Win32.cs
new file mode 100644
index 000000000..8cb464b80
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Functions/Win32.cs
@@ -0,0 +1,144 @@
+/* win32.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Functions
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ /// <summary>
+ /// Win32 API calls
+ /// </summary>
+ public class Win32
+ {
+ /// <summary>
+ /// Set the Forground Window
+ /// </summary>
+ /// <param name="hWnd">
+ /// The h wnd.
+ /// </param>
+ /// <returns>
+ /// A Boolean true when complete.
+ /// </returns>
+ [DllImport("user32.dll")]
+ public static extern bool SetForegroundWindow(int hWnd);
+
+ /// <summary>
+ /// Lock the workstation
+ /// </summary>
+ [DllImport("user32.dll")]
+ public static extern void LockWorkStation();
+
+ /// <summary>
+ /// Exit Windows
+ /// </summary>
+ /// <param name="uFlags">
+ /// The u flags.
+ /// </param>
+ /// <param name="dwReason">
+ /// The dw reason.
+ /// </param>
+ /// <returns>
+ /// an integer
+ /// </returns>
+ [DllImport("user32.dll")]
+ public static extern int ExitWindowsEx(int uFlags, int dwReason);
+
+ /// <summary>
+ /// Memory Status EX Struct
+ /// </summary>
+ public struct MEMORYSTATUSEX
+ {
+ public int dwLength;
+ public int dwMemoryLoad;
+ public ulong ullTotalPhys;
+ public ulong ullAvailPhys;
+ public ulong ullTotalPageFile;
+ public ulong ullAvailPageFile;
+ public ulong ullTotalVirtual;
+ public ulong ullAvailVirtual;
+ public ulong ullAvailExtendedVirtual;
+ }
+
+ /// <summary>
+ /// Get the System Memory information
+ /// </summary>
+ /// <param name="lpBuffer">
+ /// The lp buffer.
+ /// </param>
+ /// <returns>
+ /// A boolean.
+ /// </returns>
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
+
+
+ /// <summary>
+ /// Generate a Console Ctrl Event
+ /// </summary>
+ /// <param name="sigevent">
+ /// The sigevent.
+ /// </param>
+ /// <param name="dwProcessGroupId">
+ /// The dw process group id.
+ /// </param>
+ /// <returns>
+ /// Bool true is sucess
+ /// </returns>
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool GenerateConsoleCtrlEvent(ConsoleCtrlEvent sigevent, int dwProcessGroupId);
+
+ /// <summary>
+ /// Console Ctrl Event
+ /// </summary>
+ public enum ConsoleCtrlEvent
+ {
+ /// <summary>
+ /// Ctrl - C
+ /// </summary>
+ CTRL_C = 0,
+
+ /// <summary>
+ /// Ctrl - Break
+ /// </summary>
+ CTRL_BREAK = 1,
+
+ /// <summary>
+ /// Ctrl - Close
+ /// </summary>
+ CTRL_CLOSE = 2,
+ }
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
+
+ /// <summary>
+ /// Execution State
+ /// </summary>
+ [FlagsAttribute]
+ public enum EXECUTION_STATE : uint
+ {
+ ES_SYSTEM_REQUIRED = 0x00000001,
+ ES_CONTINUOUS = 0x80000000,
+ ES_AWAYMODE_REQUIRED = 0x00000040
+ }
+
+ /// <summary>
+ /// Prevent the system from sleeping
+ /// </summary>
+ public static void PreventSleep()
+ {
+ SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_AWAYMODE_REQUIRED);
+ }
+
+ /// <summary>
+ /// Allow the system to sleep.
+ /// </summary>
+ public static void AllowSleep()
+ {
+ SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
+ }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Functions/Win7.cs b/win/CS/HandBrake.ApplicationServices/Functions/Win7.cs
new file mode 100644
index 000000000..8d694d2f8
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Functions/Win7.cs
@@ -0,0 +1,73 @@
+/* Win7.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Functions
+{
+ using System;
+ using Microsoft.WindowsAPICodePack.Taskbar;
+
+ /// <summary>
+ /// A class implimenting Windows 7 Specific features
+ /// </summary>
+ public class Win7
+ {
+ /// <summary>
+ /// The Windows Taskbar
+ /// </summary>
+ private TaskbarManager windowsTaskbar;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Win7"/> class.
+ /// </summary>
+ public Win7()
+ {
+ if (IsWindowsSeven)
+ {
+ windowsTaskbar = TaskbarManager.Instance;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this is Windows Seven.
+ /// </summary>
+ public bool IsWindowsSeven
+ {
+ get
+ {
+ OperatingSystem os = Environment.OSVersion;
+ return os.Version.Major >= 6 && os.Version.Minor >= 1;
+ }
+ }
+
+ /// <summary>
+ /// Set the Task Bar Percentage.
+ /// </summary>
+ /// <param name="percentage">
+ /// The percentage.
+ /// </param>
+ public void SetTaskBarProgress(int percentage)
+ {
+ if (!IsWindowsSeven)
+ {
+ return;
+ }
+ windowsTaskbar.SetProgressState(TaskbarProgressBarState.Normal);
+ windowsTaskbar.SetProgressValue(percentage, 100);
+ }
+
+ /// <summary>
+ /// Disable Task Bar Progress
+ /// </summary>
+ public void SetTaskBarProgressToNoProgress()
+ {
+ if (!IsWindowsSeven)
+ {
+ return;
+ }
+
+ windowsTaskbar.SetProgressState(TaskbarProgressBarState.NoProgress);
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj b/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj
new file mode 100644
index 000000000..07aef5609
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{087A2BA8-BAC2-4577-A46F-07FF9D420016}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>HandBrake.ApplicationServices</RootNamespace>
+ <AssemblyName>HandBrake.ApplicationServices</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'NightlyBuild|AnyCPU' ">
+ <OutputPath>bin\NightlyBuild\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Growl.Connector, Version=2.0.0.0, Culture=neutral, PublicKeyToken=980c2339411be384, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\libraries\Growl.Connector.dll</HintPath>
+ </Reference>
+ <Reference Include="Growl.CoreLibrary, Version=2.0.0.0, Culture=neutral, PublicKeyToken=13e59d82e007b064, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\libraries\Growl.CoreLibrary.dll</HintPath>
+ </Reference>
+ <Reference Include="HandBrakeInterop">
+ <HintPath>..\libraries\HandBrakeInterop.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.WindowsAPICodePack, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\libraries\Microsoft.WindowsAPICodePack.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\libraries\Microsoft.WindowsAPICodePack.Shell.dll</HintPath>
+ </Reference>
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="WindowsBase" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="EventArgs\EncodeCompletedEventArgs.cs" />
+ <Compile Include="EventArgs\EncodeProgressEventArgs.cs" />
+ <Compile Include="EventArgs\QueueProgressEventArgs.cs" />
+ <Compile Include="EventArgs\ScanCompletedEventArgs.cs" />
+ <Compile Include="EventArgs\ScanProgressEventArgs.cs" />
+ <Compile Include="Functions\Converters.cs" />
+ <Compile Include="Functions\EnumHelper.cs" />
+ <Compile Include="Functions\GrowlCommunicator.cs" />
+ <Compile Include="Functions\PlistHelper.cs" />
+ <Compile Include="Functions\System.cs" />
+ <Compile Include="Functions\Win32.cs" />
+ <Compile Include="Functions\Win7.cs" />
+ <Compile Include="Init.cs" />
+ <Compile Include="Model\DriveInformation.cs" />
+ <Compile Include="Model\Encoding\AudioTrack.cs" />
+ <Compile Include="Model\Encoding\Anamorphic.cs" />
+ <Compile Include="Model\Encoding\AudioEncoder.cs" />
+ <Compile Include="Model\Encoding\FramerateMode.cs" />
+ <Compile Include="Model\Encoding\Mixdown.cs" />
+ <Compile Include="Model\Encoding\PointToPointMode.cs" />
+ <Compile Include="Model\Encoding\Cropping.cs" />
+ <Compile Include="Model\EncodeTask.cs" />
+ <Compile Include="Model\Encoding\Decomb.cs" />
+ <Compile Include="Model\Encoding\Deinterlace.cs" />
+ <Compile Include="Model\Encoding\Denoise.cs" />
+ <Compile Include="Model\Encoding\Detelecine.cs" />
+ <Compile Include="Model\Encoding\OutputFormat.cs" />
+ <Compile Include="Model\Encoding\SubtitleTrack.cs" />
+ <Compile Include="Model\Encoding\VideoEncoder.cs" />
+ <Compile Include="Model\Encoding\VideoEncodeRateMode.cs" />
+ <Compile Include="Model\General\UpdateCheckInformation.cs" />
+ <Compile Include="Model\General\UpdateCheckResult.cs" />
+ <Compile Include="Model\Preset.cs" />
+ <Compile Include="Model\QueueTask.cs" />
+ <Compile Include="Model\Encoding\SubtitleType.cs" />
+ <Compile Include="Parsing\AudioTrack.cs" />
+ <Compile Include="Parsing\Chapter.cs" />
+ <Compile Include="Parsing\Source.cs" />
+ <Compile Include="Parsing\Parser.cs" />
+ <Compile Include="Parsing\Subtitle.cs" />
+ <Compile Include="Parsing\Title.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Services\Encode.cs" />
+ <Compile Include="Services\Interfaces\IEncode.cs" />
+ <Compile Include="Services\Interfaces\IQueueManager.cs" />
+ <Compile Include="Services\Interfaces\IQueueProcessor.cs" />
+ <Compile Include="Services\Interfaces\IScan.cs" />
+ <Compile Include="Services\Interfaces\IPresetService.cs" />
+ <Compile Include="Services\LibScan.cs" />
+ <Compile Include="Services\PresetService.cs" />
+ <Compile Include="Services\QueueManager.cs" />
+ <Compile Include="Services\QueueProcessor.cs" />
+ <Compile Include="Services\ScanService.cs" />
+ <Compile Include="Services\UpdateService.cs" />
+ <Compile Include="Utilities\AppcastReader.cs" />
+ <Compile Include="Utilities\PlistUtility.cs" />
+ <Compile Include="Utilities\QueryParserUtility.cs" />
+ <Compile Include="Utilities\UtilityService.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Properties\AssemblyInfo.cs.tmpl" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\logo64.png" />
+ </ItemGroup>
+ <ItemGroup />
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(ProgramFiles)\MSBuild\Microsoft\StyleCop\v4.4\Microsoft.StyleCop.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <PropertyGroup>
+ <PreBuildEvent>
+ subwcrev.exe "$(ProjectDir)." "$(ProjectDir)Properties\AssemblyInfo.cs.tmpl" "$(ProjectDir)Properties\AssemblyInfo.cs"
+ subwcrev.exe "$(ProjectDir)." "$(ProjectDir)Properties\AssemblyInfo.cs.tmpl" "$(ProjectDir)Properties\AssemblyInfo.cs"
+ </PreBuildEvent>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Init.cs b/win/CS/HandBrake.ApplicationServices/Init.cs
new file mode 100644
index 000000000..e51683ab8
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Init.cs
@@ -0,0 +1,160 @@
+/* Init.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices
+{
+ using System;
+ using System.Reflection;
+
+ /// <summary>
+ /// Initialize ApplicationServices
+ /// </summary>
+ public class Init
+ {
+ /**
+ * I really dislike this, Need to replace this sooner rather than later.
+ **/
+
+ /// <summary>
+ /// Setup the Settings used by the applicaiton with this library
+ /// </summary>
+ /// <param name="versionString">
+ /// The version / name of the application that's using this DLL.
+ /// </param>
+ /// <param name="instanceId">
+ /// The Instance ID
+ /// </param>
+ /// <param name="completionOption">
+ /// The completion option.
+ /// </param>
+ /// <param name="disableDvdNav">
+ /// The disable dvd nav.
+ /// </param>
+ /// <param name="growlEncode">
+ /// The growl encode.
+ /// </param>
+ /// <param name="growlQueue">
+ /// The growl queue.
+ /// </param>
+ /// <param name="processPriority">
+ /// The process priority.
+ /// </param>
+ /// <param name="saveLogPath">
+ /// The save log path.
+ /// </param>
+ /// <param name="saveLogToSpecifiedPath">
+ /// The save log to specified path.
+ /// </param>
+ /// <param name="saveLogWithVideo">
+ /// The save log with video.
+ /// </param>
+ /// <param name="showCliForInGuiEncodeStatus">
+ /// The show cli for in gui encode status.
+ /// </param>
+ /// <param name="preventSleep">
+ /// Prevent the system from sleeping
+ /// </param>
+ public static void SetupSettings(string versionString, string version, int build, int instanceId, string completionOption, bool disableDvdNav,
+ bool growlEncode, bool growlQueue, string processPriority, string saveLogPath, bool saveLogToSpecifiedPath,
+ bool saveLogWithVideo, bool showCliForInGuiEncodeStatus, bool preventSleep)
+ {
+ InstanceId = instanceId;
+ HandBrakeGuiVersionString = versionString;
+ Version = version;
+ Build = build;
+ CompletionOption = completionOption;
+ DisableDvdNav = disableDvdNav;
+ GrowlEncode = growlEncode;
+ GrowlQueue = growlQueue;
+ ProcessPriority = processPriority;
+ SaveLogPath = saveLogPath;
+ SaveLogToSpecifiedPath = saveLogToSpecifiedPath;
+ SaveLogWithVideo = saveLogWithVideo;
+ ShowCliForInGuiEncodeStatus = showCliForInGuiEncodeStatus;
+ PreventSleep = preventSleep;
+ }
+
+ /// <summary>
+ /// Gets the Assembly version.
+ /// </summary>
+ /// <returns>
+ /// Version data
+ /// </returns>
+ public static Version AssemblyVersion()
+ {
+ return Assembly.GetExecutingAssembly().GetName().Version;
+ }
+
+ /// <summary>
+ /// The instance ID used by the Main Applicaiton
+ /// </summary>
+ public static int InstanceId;
+
+ /// <summary>
+ /// The Applicaiton that uses this DLL can pass in it's version string.
+ /// </summary>
+ public static string HandBrakeGuiVersionString;
+
+ /// <summary>
+ /// HandBrakes Version or Svn revision
+ /// </summary>
+ public static string Version;
+
+ /// <summary>
+ /// Handbrakes Build number
+ /// </summary>
+ public static int Build;
+
+ /// <summary>
+ /// What to do when the encode completes.
+ /// </summary>
+ public static string CompletionOption;
+
+ /// <summary>
+ /// Disable LibDvdNav
+ /// </summary>
+ public static bool DisableDvdNav;
+
+ /// <summary>
+ /// Growl when an encode has finished.
+ /// </summary>
+ public static bool GrowlEncode;
+
+ /// <summary>
+ /// Growl when a queue has finished.
+ /// </summary>
+ public static bool GrowlQueue;
+
+ /// <summary>
+ /// The Process Priority for HandBrakeCLI
+ /// </summary>
+ public static string ProcessPriority;
+
+ /// <summary>
+ /// Path to save log files to.
+ /// </summary>
+ public static string SaveLogPath;
+
+ /// <summary>
+ /// Copy log files to the SaveLogPath
+ /// </summary>
+ public static bool SaveLogToSpecifiedPath;
+
+ /// <summary>
+ /// Save a copy of the log files with the video
+ /// </summary>
+ public static bool SaveLogWithVideo;
+
+ /// <summary>
+ /// Show the CLI window when encoding.
+ /// </summary>
+ public static bool ShowCliForInGuiEncodeStatus;
+
+ /// <summary>
+ /// Prevent system sleep
+ /// </summary>
+ public static bool PreventSleep;
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/DriveInformation.cs b/win/CS/HandBrake.ApplicationServices/Model/DriveInformation.cs
new file mode 100644
index 000000000..65708cee2
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/DriveInformation.cs
@@ -0,0 +1,44 @@
+/* DriveInformation.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model
+{
+ /// <summary>
+ /// Information about a DVD drive
+ /// </summary>
+ public class DriveInformation
+ {
+ /// <summary>
+ /// Gets or sets A Unique ID That represemts this model.
+ /// </summary>
+ public int Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets The Drive Volume Name
+ /// </summary>
+ public string VolumeLabel { get; set; }
+
+ /// <summary>
+ /// Gets or sets The Root Directory
+ /// </summary>
+ public string RootDirectory { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this is a BluRay Drive.
+ /// </summary>
+ public bool IsBluRay { get; set; }
+
+ /// <summary>
+ /// Returns "Drive" + Id (e.g Drive2)
+ /// </summary>
+ /// <returns>
+ /// A String that contrains "Drive" and it's ID
+ /// </returns>
+ public override string ToString()
+ {
+ return "Drive" + this.Id;
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Model/EncodeTask.cs b/win/CS/HandBrake.ApplicationServices/Model/EncodeTask.cs
new file mode 100644
index 000000000..d600ba81c
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/EncodeTask.cs
@@ -0,0 +1,326 @@
+/* EncodeTask.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model
+{
+ using System.Collections.Generic;
+
+ using HandBrake.ApplicationServices.Model.Encoding;
+
+ /// <summary>
+ /// An Encode Task
+ /// </summary>
+ public class EncodeTask
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EncodeTask"/> class.
+ /// </summary>
+ public EncodeTask()
+ {
+ this.Cropping = new Cropping();
+ }
+
+ #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 LargeFile.
+ /// </summary>
+ public bool LargeFile { 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 a value indicating whether CustomCropping.
+ /// </summary>
+ public bool IsCustomCropping { get; set; }
+
+ /// <summary>
+ /// Gets or sets Cropping.
+ /// </summary>
+ public Cropping Cropping { 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 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 VideoEncodeRateMode 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 List<AudioTrack> AudioTracks { get; set; }
+ #endregion
+
+ #region Subtitles
+
+ /// <summary>
+ /// Gets or sets SubtitleTracks.
+ /// </summary>
+ public List<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; }
+
+ #endregion
+
+ #region Advanced
+
+ /// <summary>
+ /// Gets or sets AdvancedEncoderOptions.
+ /// </summary>
+ public string AdvancedEncoderOptions { get; set; }
+
+ #endregion
+
+ #region Preset Information (TODO This should probably be dropped)
+
+ /// <summary>
+ /// Gets or sets PresetBuildNumber.
+ /// </summary>
+ public int PresetBuildNumber { get; set; }
+
+ /// <summary>
+ /// Gets or sets PresetDescription.
+ /// </summary>
+ public string PresetDescription { get; set; }
+
+ /// <summary>
+ /// Gets or sets PresetName.
+ /// </summary>
+ public string PresetName { get; set; }
+
+ /// <summary>
+ /// Gets or sets Type.
+ /// </summary>
+ public string Type { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether UsesMaxPictureSettings.
+ /// </summary>
+ public bool UsesMaxPictureSettings { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether UsesPictureFilters.
+ /// </summary>
+ public bool UsesPictureFilters { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether UsesPictureSettings.
+ /// </summary>
+ public bool UsesPictureSettings { get; set; }
+ #endregion
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/Anamorphic.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Anamorphic.cs
new file mode 100644
index 000000000..c958b777c
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Anamorphic.cs
@@ -0,0 +1,24 @@
+/* Anamorphic.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ using System.ComponentModel;
+
+ /// <summary>
+ /// Anamorphic Mode
+ /// </summary>
+ public enum Anamorphic
+ {
+ [Description("None")]
+ None = 0,
+ [Description("Strict")]
+ Strict,
+ [Description("Loose")]
+ Loose,
+ [Description("Custom")]
+ Custom
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/AudioEncoder.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/AudioEncoder.cs
new file mode 100644
index 000000000..c6f838ed7
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/AudioEncoder.cs
@@ -0,0 +1,33 @@
+/* AudioEncoder.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ using System.ComponentModel;
+
+ public enum AudioEncoder
+ {
+ [Description("AAC (faac)")]
+ Faac = 0,
+
+ [Description("MP3 (lame)")]
+ Lame,
+
+ [Description("AC3 (ffmpeg)")]
+ Ac3,
+
+ [Description("Passthrough (AC3/DTS)")]
+ Passthrough,
+
+ [Description("Passthrough (AC3)")]
+ Ac3Passthrough,
+
+ [Description("Passthrough (DTS)")]
+ DtsPassthrough,
+
+ [Description("Vorbis (vorbis)")]
+ Vorbis
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/AudioTrack.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/AudioTrack.cs
new file mode 100644
index 000000000..bcfb27089
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/AudioTrack.cs
@@ -0,0 +1,56 @@
+/* AudioTrack.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ /// <summary>
+ /// An Audio Track for the Audio Panel
+ /// </summary>
+ public class AudioTrack
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AudioTrack"/> class.
+ /// </summary>
+ public AudioTrack()
+ {
+ // Default Values
+ this.Track = "Automatic";
+ this.MixDown = "Automatic";
+ this.SampleRate = "Auto";
+ this.Bitrate = "Auto";
+ this.DRC = "1";
+ }
+
+ /// <summary>
+ /// Gets or sets Audio Track Name
+ /// </summary>
+ public string Track { get; set; }
+
+ /// <summary>
+ /// Gets or sets Audio Mixdown
+ /// </summary>
+ public string MixDown { get; set; }
+
+ /// <summary>
+ /// Gets or sets Audio Encoder
+ /// </summary>
+ public string Encoder { get; set; }
+
+ /// <summary>
+ /// Gets or sets Audio Bitrate
+ /// </summary>
+ public string Bitrate { get; set; }
+
+ /// <summary>
+ /// Gets or sets Audio SampleRate
+ /// </summary>
+ public string SampleRate { get; set; }
+
+ /// <summary>
+ /// Gets or sets Dynamic Range Compression
+ /// </summary>
+ public string DRC { get; set; }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/Cropping.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Cropping.cs
new file mode 100644
index 000000000..2ec98aaca
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Cropping.cs
@@ -0,0 +1,63 @@
+/* Cropping.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ /// <summary>
+ /// Cropping T B L R
+ /// </summary>
+ public class Cropping
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Cropping"/> class.
+ /// </summary>
+ public Cropping()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Cropping"/> class.
+ /// </summary>
+ /// <param name="top">
+ /// The Top Value
+ /// </param>
+ /// <param name="bottom">
+ /// The Bottom Value
+ /// </param>
+ /// <param name="left">
+ /// The Left Value
+ /// </param>
+ /// <param name="right">
+ /// The Right Value
+ /// </param>
+ public Cropping(int top, int bottom, int left, int right)
+ {
+ this.Top = top;
+ this.Bottom = bottom;
+ this.Left = left;
+ this.Right = right;
+ }
+
+ /// <summary>
+ /// Gets or sets Top.
+ /// </summary>
+ public int Top { get; set; }
+
+ /// <summary>
+ /// Gets or sets Bottom.
+ /// </summary>
+ public int Bottom { get; set; }
+
+ /// <summary>
+ /// Gets or sets Left.
+ /// </summary>
+ public int Left { get; set; }
+
+ /// <summary>
+ /// Gets or sets Right.
+ /// </summary>
+ public int Right { get; set; }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/Decomb.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Decomb.cs
new file mode 100644
index 000000000..ae8b8a3d4
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Decomb.cs
@@ -0,0 +1,17 @@
+/* Decomb.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ /// <summary>
+ /// Decomb Mode
+ /// </summary>
+ public enum Decomb
+ {
+ Off = 0,
+ Default,
+ Custom
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/Deinterlace.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Deinterlace.cs
new file mode 100644
index 000000000..38dadd04e
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Deinterlace.cs
@@ -0,0 +1,20 @@
+/* Deinterlace.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ /// <summary>
+ /// The Deinterlace Filter
+ /// </summary>
+ public enum Deinterlace
+ {
+ Off = 0,
+ Fast,
+ Slow,
+ Slower,
+ Slowest,
+ Custom
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/Denoise.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Denoise.cs
new file mode 100644
index 000000000..fc81e9f20
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Denoise.cs
@@ -0,0 +1,19 @@
+/* Denoise.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ /// <summary>
+ /// The Denose Filters
+ /// </summary>
+ public enum Denoise
+ {
+ Off = 0,
+ Weak,
+ Medium,
+ Strong,
+ Custom
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/Detelecine.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Detelecine.cs
new file mode 100644
index 000000000..09c948dbd
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Detelecine.cs
@@ -0,0 +1,17 @@
+/* Detelecine.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ /// <summary>
+ /// Detelecine Filter
+ /// </summary>
+ public enum Detelecine
+ {
+ Off = 0,
+ Default,
+ Custom
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/FramerateMode.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/FramerateMode.cs
new file mode 100644
index 000000000..508e63ced
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/FramerateMode.cs
@@ -0,0 +1,17 @@
+/* VideoEncoderMode.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ /// <summary>
+ /// The Mode of Video Encoding. CFR, VFR, PFR
+ /// </summary>
+ public enum FramerateMode
+ {
+ CFR = 0,
+ PFR,
+ VFR
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/Mixdown.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Mixdown.cs
new file mode 100644
index 000000000..12611b454
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/Mixdown.cs
@@ -0,0 +1,33 @@
+/* Mixdown.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ using System.ComponentModel;
+
+ /// <summary>
+ /// The Mixdown Mode
+ /// </summary>
+ public enum Mixdown
+ {
+ [Description("Dolby Pro Logic II")]
+ DolbyProLogicII = 0,
+
+ [Description("Auto")]
+ Auto,
+
+ [Description("Mono")]
+ Mono,
+
+ [Description("Stereo")]
+ Stereo,
+
+ [Description("Dolby Surround")]
+ DolbySurround,
+
+ [Description("6 Channel Discrete")]
+ SixChannelDiscrete
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/OutputFormat.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/OutputFormat.cs
new file mode 100644
index 000000000..fa5c3225f
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/OutputFormat.cs
@@ -0,0 +1,24 @@
+/* OutputFormat.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ using System.ComponentModel;
+
+ /// <summary>
+ /// The Output format.
+ /// </summary>
+ public enum OutputFormat
+ {
+ [Description("MP4")]
+ Mp4,
+
+ [Description("M4V")]
+ M4V,
+
+ [Description("MKV")]
+ Mkv
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/PointToPointMode.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/PointToPointMode.cs
new file mode 100644
index 000000000..dcee4cac4
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/PointToPointMode.cs
@@ -0,0 +1,17 @@
+/* PointToPoint.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ /// <summary>
+ /// Point to Point Mode
+ /// </summary>
+ public enum PointToPointMode
+ {
+ Chapters = 0,
+ Seconds,
+ Frames
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/SubtitleTrack.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/SubtitleTrack.cs
new file mode 100644
index 000000000..f69abed7d
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/SubtitleTrack.cs
@@ -0,0 +1,95 @@
+/* SubtitleTrack.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ using System.Windows.Forms;
+
+ /// <summary>
+ /// Subtitle Information
+ /// </summary>
+ public class SubtitleTrack
+ {
+ /// <summary>
+ /// Gets or sets Track.
+ /// </summary>
+ public string Track { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether Forced.
+ /// </summary>
+ public bool Forced { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether Burned.
+ /// </summary>
+ public bool Burned { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether Default.
+ /// </summary>
+ public bool Default { get; set; }
+
+ #region SRT Specific Options
+
+ /// <summary>
+ /// Gets or sets the SRT Language
+ /// </summary>
+ public string SrtLang { get; set; }
+
+ /// <summary>
+ /// Gets or sets the SRT Character Code
+ /// </summary>
+ public string SrtCharCode { 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 SRT Filename
+ /// </summary>
+ public string SrtFileName { get; set; }
+
+ /// <summary>
+ /// Gets a value indicating whether this is an SRT subtitle.
+ /// </summary>
+ public bool IsSrtSubtitle
+ {
+ get { return this.SrtFileName != "-"; }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Gets or sets the type of the subtitle
+ /// </summary>
+ public SubtitleType SubtitleType { get; set; }
+
+ /// <summary>
+ /// Gets A ListViewItem Containing information about this subitlte
+ /// </summary>
+ public ListViewItem ListView
+ {
+ get
+ {
+ var listTrack = new ListViewItem(this.Track);
+ listTrack.SubItems.Add(this.Forced ? "Yes" : "No");
+ listTrack.SubItems.Add(this.Burned ? "Yes" : "No");
+ listTrack.SubItems.Add(this.Default ? "Yes" : "No");
+ listTrack.SubItems.Add(this.SrtLang);
+ listTrack.SubItems.Add(this.SrtCharCode);
+ listTrack.SubItems.Add(this.SrtOffset.ToString());
+ return listTrack;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/SubtitleType.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/SubtitleType.cs
new file mode 100644
index 000000000..5a69d0105
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/SubtitleType.cs
@@ -0,0 +1,30 @@
+/* SubtitleType.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ 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("Unknown")]
+ Unknown
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/VideoEncodeRateMode.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/VideoEncodeRateMode.cs
new file mode 100644
index 000000000..636d7829d
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/VideoEncodeRateMode.cs
@@ -0,0 +1,17 @@
+/* VideoEncoderRateMode.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ /// <summary>
+ /// The Mode of Video Encoding. Bitrate, Filesize or Quality
+ /// </summary>
+ public enum VideoEncodeRateMode
+ {
+ TargetSize = 0,
+ AverageBitrate,
+ ConstantQuality
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Encoding/VideoEncoder.cs b/win/CS/HandBrake.ApplicationServices/Model/Encoding/VideoEncoder.cs
new file mode 100644
index 000000000..b5a2556e3
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Encoding/VideoEncoder.cs
@@ -0,0 +1,24 @@
+/* VideoEncoder.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.Encoding
+{
+ using System.ComponentModel;
+
+ /// <summary>
+ /// The Video Encoder
+ /// </summary>
+ public enum VideoEncoder
+ {
+ [Description("H.264 (x264)")]
+ X264 = 0,
+
+ [Description("MPEG-4 (FFMpeg)")]
+ FFMpeg,
+
+ [Description("VP3 (Theora)")]
+ Theora
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/General/UpdateCheckInformation.cs b/win/CS/HandBrake.ApplicationServices/Model/General/UpdateCheckInformation.cs
new file mode 100644
index 000000000..5932aa402
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/General/UpdateCheckInformation.cs
@@ -0,0 +1,53 @@
+/* UpdateCheckInformation.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.General
+{
+ using System;
+
+ /// <summary>
+ /// Provides information about an update check.
+ /// </summary>
+ public struct UpdateCheckInformation
+ {
+ /// <summary>
+ /// Gets or sets a value indicating whether a New Version is Available.
+ /// </summary>
+ public bool NewVersionAvailable { get; set; }
+
+ /// <summary>
+ /// Gets a value indicating whether an Error Occured.
+ /// </summary>
+ public bool ErrorOccured
+ {
+ get { return this.Error != null; }
+ }
+
+ /// <summary>
+ /// Gets or sets Information about an update to HandBrake
+ /// </summary>
+ public Uri DescriptionUrl { get; set; }
+
+ /// <summary>
+ /// Gets or sets HandBrake's version from the appcast.xml file.
+ /// </summary>
+ public string Version { get; set; }
+
+ /// <summary>
+ /// Gets or sets HandBrake's Build from the appcast.xml file.
+ /// </summary>
+ public string Build { get; set; }
+
+ /// <summary>
+ /// Gets or sets the URL for update file.
+ /// </summary>
+ public string DownloadFile { get; set; }
+
+ /// <summary>
+ /// Gets or sets the error that occurred, if any. This will be null if no error occured.
+ /// </summary>
+ public Exception Error { get; set; }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/General/UpdateCheckResult.cs b/win/CS/HandBrake.ApplicationServices/Model/General/UpdateCheckResult.cs
new file mode 100644
index 000000000..2f7c7e874
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/General/UpdateCheckResult.cs
@@ -0,0 +1,71 @@
+/* UpdateCheckResult.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model.General
+{
+ using System;
+ using System.Threading;
+
+ /// <summary>
+ /// Used in EndUpdateCheck() for update checking and the IAsyncResult design pattern.
+ /// </summary>
+ public class UpdateCheckResult : IAsyncResult
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UpdateCheckResult"/> class.
+ /// </summary>
+ /// <param name="asyncState">
+ /// The async state.
+ /// </param>
+ /// <param name="info">
+ /// The info.
+ /// </param>
+ public UpdateCheckResult(object asyncState, ApplicationServices.Model.General.UpdateCheckInformation info)
+ {
+ this.AsyncState = asyncState;
+ this.Result = info;
+ }
+
+ /// <summary>
+ /// Gets whether the check was executed in debug mode.
+ /// </summary>
+ public object AsyncState { get; private set; }
+
+ /// <summary>
+ /// Gets the result of the update check.
+ /// </summary>
+ public ApplicationServices.Model.General.UpdateCheckInformation Result { get; private set; }
+
+ /// <summary>
+ /// Gets AsyncWaitHandle.
+ /// </summary>
+ /// <exception cref="NotImplementedException">
+ /// </exception>
+ public WaitHandle AsyncWaitHandle
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether CompletedSynchronously.
+ /// </summary>
+ /// <exception cref="NotImplementedException">
+ /// </exception>
+ public bool CompletedSynchronously
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether IsCompleted.
+ /// </summary>
+ /// <exception cref="NotImplementedException">
+ /// </exception>
+ public bool IsCompleted
+ {
+ get { throw new NotImplementedException(); }
+ }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Model/Preset.cs b/win/CS/HandBrake.ApplicationServices/Model/Preset.cs
new file mode 100644
index 000000000..e20ad2dee
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/Preset.cs
@@ -0,0 +1,64 @@
+/* Preset.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model
+{
+ /// <summary>
+ /// A Preset for encoding with.
+ /// </summary>
+ public class Preset
+ {
+ /// <summary>
+ /// Gets or sets the category which the preset resides under
+ /// </summary>
+ public string Category { get; set; }
+
+ /// <summary>
+ /// Gets or sets the preset name
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the preset query
+ /// </summary>
+ public string Query { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether to use picture Settings in presets.
+ /// </summary>
+ public bool CropSettings { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Settings for this encode/preset. Can be used in place of Query property.
+ /// </summary>
+ public EncodeTask EncodeSettings { get; set; }
+
+ /// <summary>
+ /// Gets or sets The version number which associates this preset with a HB build
+ /// </summary>
+ public string Version { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Description for the preset
+ /// </summary>
+ public string Description { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this is a built in preset
+ /// </summary>
+ public bool IsBuildIn { get; set; }
+
+ /// <summary>
+ /// Override the ToString Method
+ /// </summary>
+ /// <returns>
+ /// The Preset Name
+ /// </returns>
+ public override string ToString()
+ {
+ return this.Name;
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Model/QueueTask.cs b/win/CS/HandBrake.ApplicationServices/Model/QueueTask.cs
new file mode 100644
index 000000000..83948a1f3
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Model/QueueTask.cs
@@ -0,0 +1,84 @@
+/* QueueTask.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Model
+{
+ /// <summary>
+ /// The QueueTask.
+ /// </summary>
+ public class QueueTask
+ {
+ /*
+ * TODO
+ * - Update the Query property to generate the query from the EncodeTask object.
+ * - Remove Sourcee, Destination and Title when they are no longer used.
+ */
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="QueueTask"/> class.
+ /// </summary>
+ public QueueTask()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="QueueTask"/> class.
+ /// </summary>
+ /// <param name="query">
+ /// The query.
+ /// </param>
+ public QueueTask(string query)
+ {
+ this.Query = query;
+ }
+
+ /// <summary>
+ /// Gets or sets the job ID.
+ /// </summary>
+ public int Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets Title.
+ /// </summary>
+ public int Title { get; set; }
+
+ /// <summary>
+ /// Gets or sets Source.
+ /// </summary>
+ public string Source { get; set; }
+
+ /// <summary>
+ /// Gets or sets Destination.
+ /// </summary>
+ public string Destination { get; set; }
+
+ /// <summary>
+ /// Gets or sets the query string.
+ /// </summary>
+ public string Query { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether if this is a user or GUI generated query
+ /// </summary>
+ public bool CustomQuery { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Encode Task.
+ /// </summary>
+ public EncodeTask Task { get; set; }
+
+ /// <summary>
+ /// Gets a value indicating whether or not this instance is empty.
+ /// </summary>
+ public bool IsEmpty
+ {
+ get
+ {
+ return this.Id == 0 && string.IsNullOrEmpty(this.Query) && string.IsNullOrEmpty(this.Task.Source) &&
+ string.IsNullOrEmpty(this.Task.Destination);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Parsing/AudioTrack.cs b/win/CS/HandBrake.ApplicationServices/Parsing/AudioTrack.cs
new file mode 100644
index 000000000..0597f4d1b
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Parsing/AudioTrack.cs
@@ -0,0 +1,169 @@
+/* AudioTrack.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Parsing
+{
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text.RegularExpressions;
+
+ /// <summary>
+ /// An object represending an AudioTrack associated with a Title, in a DVD
+ /// </summary>
+ public class AudioTrack
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AudioTrack"/> class.
+ /// </summary>
+ public AudioTrack()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AudioTrack"/> 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 AudioTrack(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>
+ /// Parse the CLI input to an Audio Track object
+ /// </summary>
+ /// <param name="output">
+ /// The output.
+ /// </param>
+ /// <returns>
+ /// An Audio Track obkect
+ /// </returns>
+ public static AudioTrack Parse(StringReader output)
+ {
+ string audioTrack = output.ReadLine();
+ Match m = Regex.Match(audioTrack, @"^ \+ ([0-9]*), ([A-Za-z0-9,\s]*) \((.*)\) \((.*)\)");
+ Match track = Regex.Match(audioTrack, @"^ \+ ([0-9]*), ([A-Za-z0-9,\s]*) \((.*)\)"); // ID and Language
+ Match iso639_2 = Regex.Match(audioTrack, @"iso639-2: ([a-zA-Z]*)\)");
+ Match samplerate = Regex.Match(audioTrack, @"([0-9]*)Hz");
+ Match bitrate = Regex.Match(audioTrack, @"([0-9]*)bps");
+
+ string subformat = m.Groups[4].Value.Trim().Contains("iso639") ? null : m.Groups[4].Value;
+ string samplerateVal = samplerate.Success ? samplerate.Groups[0].Value.Replace("Hz", string.Empty).Trim() : "0";
+ string bitrateVal = bitrate.Success ? bitrate.Groups[0].Value.Replace("bps", string.Empty).Trim() : "0";
+
+ if (track.Success)
+ {
+ var thisTrack = new AudioTrack
+ {
+ TrackNumber = int.Parse(track.Groups[1].Value.Trim()),
+ Language = track.Groups[2].Value,
+ Format = m.Groups[3].Value,
+ Description = subformat,
+ SampleRate = int.Parse(samplerateVal),
+ Bitrate = int.Parse(bitrateVal),
+ LanguageCode = iso639_2.Value.Replace("iso639-2: ", string.Empty).Replace(")", string.Empty)
+ };
+ return thisTrack;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Pase a list of audio tracks
+ /// </summary>
+ /// <param name="output">
+ /// The output.
+ /// </param>
+ /// <returns>
+ /// An array of audio tracks
+ /// </returns>
+ public static AudioTrack[] ParseList(StringReader output)
+ {
+ var tracks = new List<AudioTrack>();
+ while (true)
+ {
+ AudioTrack thisTrack = Parse(output);
+ if (thisTrack != null)
+ tracks.Add(thisTrack);
+ else
+ break;
+ }
+ return tracks.ToArray();
+ }
+
+ /// <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 (Description == null)
+ return string.Format("{0} {1} ({2})", TrackNumber, Language, Format);
+
+ return string.Format("{0} {1} ({2}) ({3})", TrackNumber, Language, Format, Description);
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Parsing/Chapter.cs b/win/CS/HandBrake.ApplicationServices/Parsing/Chapter.cs
new file mode 100644
index 000000000..4ec76fa1c
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Parsing/Chapter.cs
@@ -0,0 +1,126 @@
+/* Chapter.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Parsing
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text.RegularExpressions;
+
+ /// <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>
+ /// Parse a CLI string to a Chapter object
+ /// </summary>
+ /// <param name="output">
+ /// The output.
+ /// </param>
+ /// <returns>
+ /// A chapter Object
+ /// </returns>
+ public static Chapter Parse(StringReader output)
+ {
+ // TODO add support for reading chapter names to the regex.
+ Match m = Regex.Match(
+ output.ReadLine(),
+ @"^ \+ ([0-9]*): cells ([0-9]*)->([0-9]*), ([0-9]*) blocks, duration ([0-9]{2}:[0-9]{2}:[0-9]{2})");
+ if (m.Success)
+ {
+ var thisChapter = new Chapter
+ {
+ ChapterNumber = int.Parse(m.Groups[1].Value.Trim()),
+ ChapterName = string.Empty,
+ Duration = TimeSpan.Parse(m.Groups[5].Value)
+ };
+ return thisChapter;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Prase a list of strings / chatpers
+ /// </summary>
+ /// <param name="output">
+ /// The output.
+ /// </param>
+ /// <returns>
+ /// An array of chapter objects
+ /// </returns>
+ public static Chapter[] ParseList(StringReader output)
+ {
+ var chapters = new List<Chapter>();
+
+ // this is to read the " + chapters:" line from the buffer
+ // so we can start reading the chapters themselvs
+ output.ReadLine();
+
+ while (true)
+ {
+ // Start of the chapter list for this Title
+ Chapter thisChapter = Parse(output);
+
+ if (thisChapter != null)
+ chapters.Add(thisChapter);
+ else
+ break;
+ }
+ return chapters.ToArray();
+ }
+
+ /// <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 ChapterNumber.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Parsing/Parser.cs b/win/CS/HandBrake.ApplicationServices/Parsing/Parser.cs
new file mode 100644
index 000000000..e46afea28
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Parsing/Parser.cs
@@ -0,0 +1,163 @@
+/* Parser.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Parsing
+{
+ using System;
+ using System.Globalization;
+ using System.IO;
+ using System.Text;
+ using System.Text.RegularExpressions;
+
+ /// <summary>
+ /// A delegate to handle custom events regarding data being parsed from the buffer
+ /// </summary>
+ /// <param name="sender">The object which raised this delegate</param>
+ /// <param name="data">The data parsed from the stream</param>
+ public delegate void DataReadEventHandler(object sender, string data);
+
+ /// <summary>
+ /// A delegate to handle events regarding progress during DVD scanning
+ /// </summary>
+ /// <param name="sender">The object who's raising the event</param>
+ /// <param name="currentTitle">The title number currently being processed</param>
+ /// <param name="titleCount">The total number of titiles to be processed</param>
+ public delegate void ScanProgressEventHandler(object sender, int currentTitle, int titleCount);
+
+ /// <summary>
+ /// A delegate to handle encode progress updates // EXPERIMENTAL
+ /// </summary>
+ /// <param name="sender">The object which raised the event</param>
+ /// <param name="currentTask">The current task being processed from the queue</param>
+ /// <param name="taskCount">The total number of tasks in queue</param>
+ /// <param name="percentComplete">The percentage this task is complete</param>
+ /// <param name="currentFps">The current encoding fps</param>
+ /// <param name="averageFps">The average encoding fps for this task</param>
+ /// <param name="timeRemaining">The estimated time remaining for this task to complete</param>
+ public delegate void EncodeProgressEventHandler(object sender, int currentTask, int taskCount, float percentComplete, float currentFps, float averageFps, string timeRemaining);
+
+ /// <summary>
+ /// A simple wrapper around a StreamReader to keep track of the entire output from a cli process
+ /// </summary>
+ public class Parser : StreamReader
+ {
+ /// <summary>
+ /// The Buffer StringBuilder
+ /// </summary>
+ private readonly StringBuilder buffer = new StringBuilder(string.Empty);
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Parser"/> class.
+ /// Default constructor for this object
+ /// </summary>
+ /// <param name="baseStream">
+ /// The stream to parse from
+ /// </param>
+ public Parser(Stream baseStream) : base(baseStream)
+ {
+ }
+
+ /// <summary>
+ /// Raised upon a new line being read from stdout/stderr
+ /// </summary>
+ public event DataReadEventHandler OnReadLine;
+
+ /// <summary>
+ /// Raised upon the entire stdout/stderr stream being read in a single call
+ /// </summary>
+ public event DataReadEventHandler OnReadToEnd;
+
+ /// <summary>
+ /// Raised upon the catching of a "Scanning title # of #..." in the stream
+ /// </summary>
+ public event ScanProgressEventHandler OnScanProgress;
+
+ /// <summary>
+ /// Raised upon the catching of a "Scanning title # of #..." in the stream
+ /// </summary>
+ public event EncodeProgressEventHandler OnEncodeProgress;
+
+ /// <summary>
+ /// Gets the buffer of data that came from the CLI standard input/error
+ /// </summary>
+ public StringBuilder Buffer
+ {
+ get { return buffer; }
+ }
+
+ /// <summary>
+ /// Read a line from standard in/err
+ /// </summary>
+ /// <returns>
+ /// The read line
+ /// </returns>
+ public override string ReadLine()
+ {
+ string tmp = base.ReadLine();
+
+ buffer.Append(tmp + Environment.NewLine);
+
+ Match m = null;
+ if (tmp.Contains("Scanning title"))
+ m = Regex.Match(tmp, "^Scanning title ([0-9]*) of ([0-9]*)");
+
+ if (OnReadLine != null)
+ OnReadLine(this, tmp);
+
+ if (m != null)
+ if (m.Success && OnScanProgress != null)
+ OnScanProgress(this, int.Parse(m.Groups[1].Value), int.Parse(m.Groups[2].Value));
+
+ return tmp;
+ }
+
+ /// <summary>
+ /// Read to the end of the input stream
+ /// </summary>
+ /// <returns>
+ /// A string of the input data
+ /// </returns>
+ public override string ReadToEnd()
+ {
+ string tmp = base.ReadToEnd();
+
+ buffer.Append(tmp + Environment.NewLine);
+ if (OnReadToEnd != null)
+ OnReadToEnd(this, tmp);
+
+ return tmp;
+ }
+
+ /// <summary>
+ /// Pase the CLI status output (from standard output)
+ /// </summary>
+ public void ReadEncodeStatus()
+ {
+ CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
+ string tmp = base.ReadLine();
+
+ Match m = Regex.Match(tmp, @"^Encoding: task ([0-9]*) of ([0-9]*), ([0-9]*\.[0-9]*) %( \(([0-9]*\.[0-9]*) fps, avg ([0-9]*\.[0-9]*) fps, ETA ([0-9]{2})h([0-9]{2})m([0-9]{2})s\))?");
+ if (m.Success && OnEncodeProgress != null)
+ {
+ int currentTask = int.Parse(m.Groups[1].Value);
+ int totalTasks = int.Parse(m.Groups[2].Value);
+ float percent = float.Parse(m.Groups[3].Value, culture);
+ float currentFps = m.Groups[5].Value == string.Empty ? 0.0F : float.Parse(m.Groups[5].Value, culture);
+ float avgFps = m.Groups[6].Value == string.Empty ? 0.0F : float.Parse(m.Groups[6].Value, culture);
+ string remaining = string.Empty;
+ if (m.Groups[7].Value != string.Empty)
+ {
+ remaining = m.Groups[7].Value + ":" + m.Groups[8].Value + ":" + m.Groups[9].Value;
+ }
+ if (string.IsNullOrEmpty(remaining))
+ {
+ remaining = "Calculating ...";
+ }
+
+ OnEncodeProgress(this, currentTask, totalTasks, percent, currentFps, avgFps, remaining);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Parsing/Source.cs b/win/CS/HandBrake.ApplicationServices/Parsing/Source.cs
new file mode 100644
index 000000000..0ed9c0033
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Parsing/Source.cs
@@ -0,0 +1,53 @@
+/* Source.cs $ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Parsing
+{
+ using System.Collections.Generic;
+ using System.IO;
+
+ /// <summary>
+ /// An object representing a scanned DVD
+ /// </summary>
+ public class Source
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Source"/> class.
+ /// Default constructor for this object
+ /// </summary>
+ public Source()
+ {
+ Titles = new List<Title>();
+ }
+
+ /// <summary>
+ /// Gets or sets Titles. A list of titles from the source
+ /// </summary>
+ public List<Title> Titles { get; set; }
+
+ /// <summary>
+ /// Parse the StreamReader output into a List of Titles
+ /// </summary>
+ /// <param name="output">
+ /// The output.
+ /// </param>
+ /// <returns>
+ /// A DVD object which contains a list of title inforamtion
+ /// </returns>
+ public static Source Parse(StreamReader output)
+ {
+ var thisDVD = new Source();
+
+ while (!output.EndOfStream)
+ {
+ if ((char) output.Peek() == '+')
+ thisDVD.Titles.AddRange(Title.ParseList(output.ReadToEnd()));
+ else
+ output.ReadLine();
+ }
+
+ return thisDVD;
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Parsing/Subtitle.cs b/win/CS/HandBrake.ApplicationServices/Parsing/Subtitle.cs
new file mode 100644
index 000000000..1ac827037
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Parsing/Subtitle.cs
@@ -0,0 +1,171 @@
+/* Subtitle.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Parsing
+{
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text.RegularExpressions;
+
+ using HandBrake.ApplicationServices.Functions;
+ using HandBrake.ApplicationServices.Model.Encoding;
+
+ /// <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="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>
+ public Subtitle(int trackNumber, string language, string languageCode, SubtitleType subtitleType)
+ {
+ this.TrackNumber = trackNumber;
+ this.Language = language;
+ this.LanguageCode = languageCode;
+ this.SubtitleType = subtitleType;
+ }
+
+
+ /// <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 or sets the Subtitle Type
+ /// </summary>
+ public SubtitleType SubtitleType { get; set; }
+
+ /// <summary>
+ /// Gets Subtitle Type
+ /// </summary>
+ public string TypeString
+ {
+ get
+ {
+ return EnumHelper.GetDescription(this.SubtitleType);
+ }
+ }
+
+ /// <summary>
+ /// Parse the input strings related to subtitles
+ /// </summary>
+ /// <param name="output">
+ /// The output.
+ /// </param>
+ /// <returns>
+ /// A Subitle object
+ /// </returns>
+ public static Subtitle Parse(StringReader output)
+ {
+ string curLine = output.ReadLine();
+
+ // + 1, English (iso639-2: eng) (Text)(SSA)
+ // + 1, English (iso639-2: eng) (Text)(UTF-8)
+ Match m = Regex.Match(curLine, @"^ \+ ([0-9]*), ([A-Za-z, ]*) \((.*)\) \(([a-zA-Z]*)\)\(([a-zA-Z0-9\-]*)\)");
+
+ if (m.Success && !curLine.Contains("HandBrake has exited."))
+ {
+ var thisSubtitle = new Subtitle
+ {
+ TrackNumber = int.Parse(m.Groups[1].Value.Trim()),
+ Language = m.Groups[2].Value,
+ LanguageCode = m.Groups[3].Value,
+ };
+
+ switch (m.Groups[5].Value)
+ {
+ case "VOBSUB":
+ thisSubtitle.SubtitleType = SubtitleType.VobSub;
+ break;
+ case "SRT":
+ thisSubtitle.SubtitleType = SubtitleType.SRT;
+ break;
+ case "CC":
+ thisSubtitle.SubtitleType = SubtitleType.CC;
+ break;
+ case "UTF-8":
+ thisSubtitle.SubtitleType = SubtitleType.UTF8Sub;
+ break;
+ case "TX3G":
+ thisSubtitle.SubtitleType = SubtitleType.TX3G;
+ break;
+ case "SSA":
+ thisSubtitle.SubtitleType = SubtitleType.SSA;
+ break;
+ default:
+ thisSubtitle.SubtitleType = SubtitleType.Unknown;
+ break;
+ }
+
+ return thisSubtitle;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Parse a list of Subtitle tracks from an input string.
+ /// </summary>
+ /// <param name="output">
+ /// The output.
+ /// </param>
+ /// <returns>
+ /// An array of Subtitle objects
+ /// </returns>
+ public static IEnumerable<Subtitle> ParseList(StringReader output)
+ {
+ var subtitles = new List<Subtitle>();
+ while ((char)output.Peek() != '+')
+ {
+ Subtitle thisSubtitle = Parse(output);
+
+ if (thisSubtitle != null)
+ subtitles.Add(thisSubtitle);
+ else
+ break;
+ }
+ return subtitles.ToArray();
+ }
+
+ /// <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 string.Format("{0} {1} ({2})", TrackNumber, Language, TypeString);
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Parsing/Title.cs b/win/CS/HandBrake.ApplicationServices/Parsing/Title.cs
new file mode 100644
index 000000000..3a9e6a56a
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Parsing/Title.cs
@@ -0,0 +1,234 @@
+/* Title.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Parsing
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Drawing;
+ using System.Globalization;
+ using System.IO;
+ using System.Text.RegularExpressions;
+
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Model.Encoding;
+
+ /// <summary>
+ /// An object that represents a single Title of a DVD
+ /// </summary>
+ public class Title
+ {
+ /// <summary>
+ /// The Culture Info
+ /// </summary>
+ private static readonly CultureInfo Culture = new CultureInfo("en-US", false);
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Title"/> class.
+ /// </summary>
+ public Title()
+ {
+ this.AudioTracks = new List<AudioTrack>();
+ 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<AudioTrack> 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 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 double 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 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>
+ /// Parse the Title Information
+ /// </summary>
+ /// <param name="output">A StringReader of output data</param>
+ /// <returns>A Title Object</returns>
+ public static Title Parse(StringReader output)
+ {
+ var thisTitle = new Title();
+ string nextLine = output.ReadLine();
+
+ // Get the Title Number
+ Match m = Regex.Match(nextLine, @"^\+ title ([0-9]*):");
+ if (m.Success)
+ thisTitle.TitleNumber = int.Parse(m.Groups[1].Value.Trim());
+ nextLine = output.ReadLine();
+
+ // Detect if this is the main feature
+ m = Regex.Match(nextLine, @" \+ Main Feature");
+ if (m.Success)
+ {
+ thisTitle.MainTitle = true;
+ nextLine = output.ReadLine();
+ }
+
+ // Get the stream name for file import
+ m = Regex.Match(nextLine, @"^ \+ stream:");
+ if (m.Success)
+ {
+ thisTitle.SourceName = nextLine.Replace("+ stream:", string.Empty).Trim();
+ nextLine = output.ReadLine();
+ }
+
+ // Jump over the VTS and blocks line
+ m = Regex.Match(nextLine, @"^ \+ vts:");
+ if (nextLine.Contains("blocks") || nextLine.Contains("+ vts "))
+ {
+ nextLine = output.ReadLine();
+ }
+
+ // Multi-Angle Support if LibDvdNav is enabled
+ if (!Init.DisableDvdNav)
+ {
+ m = Regex.Match(nextLine, @" \+ angle\(s\) ([0-9])");
+ if (m.Success)
+ {
+ string angleList = m.Value.Replace("+ angle(s) ", string.Empty).Trim();
+ int angleCount;
+ int.TryParse(angleList, out angleCount);
+
+ thisTitle.AngleCount = angleCount;
+ nextLine = output.ReadLine();
+ }
+ }
+
+ // Get duration for this title
+ m = Regex.Match(nextLine, @"^ \+ duration: ([0-9]{2}:[0-9]{2}:[0-9]{2})");
+ if (m.Success)
+ thisTitle.Duration = TimeSpan.Parse(m.Groups[1].Value);
+
+ // Get resolution, aspect ratio and FPS for this title
+ m = Regex.Match(output.ReadLine(), @"^ \+ size: ([0-9]*)x([0-9]*), pixel aspect: ([0-9]*)/([0-9]*), display aspect: ([0-9]*\.[0-9]*), ([0-9]*\.[0-9]*) fps");
+ if (m.Success)
+ {
+ thisTitle.Resolution = new Size(int.Parse(m.Groups[1].Value), int.Parse(m.Groups[2].Value));
+ thisTitle.ParVal = new Size(int.Parse(m.Groups[3].Value), int.Parse(m.Groups[4].Value));
+ thisTitle.AspectRatio = float.Parse(m.Groups[5].Value, Culture);
+ thisTitle.Fps = float.Parse(m.Groups[6].Value, Culture);
+ }
+
+ // Get autocrop region for this title
+ m = Regex.Match(output.ReadLine(), @"^ \+ autocrop: ([0-9]*)/([0-9]*)/([0-9]*)/([0-9]*)");
+ if (m.Success)
+ {
+ thisTitle.AutoCropDimensions = new Cropping
+ {
+ Top = int.Parse(m.Groups[1].Value),
+ Bottom = int.Parse(m.Groups[2].Value),
+ Left = int.Parse(m.Groups[3].Value),
+ Right = int.Parse(m.Groups[4].Value)
+ };
+ }
+
+ thisTitle.Chapters.AddRange(Chapter.ParseList(output));
+
+ thisTitle.AudioTracks.AddRange(AudioTrack.ParseList(output));
+
+ thisTitle.Subtitles.AddRange(Subtitle.ParseList(output));
+
+ return thisTitle;
+ }
+
+ /// <summary>
+ /// Return a list of parsed titles
+ /// </summary>
+ /// <param name="output">The Output</param>
+ /// <returns>A List of titles</returns>
+ public static Title[] ParseList(string output)
+ {
+ var titles = new List<Title>();
+ var sr = new StringReader(output);
+
+ while (sr.Peek() == '+' || sr.Peek() == ' ')
+ {
+ // If the the character is a space, then chances are the line
+ if (sr.Peek() == ' ') // If the character is a space, then chances are it's the combing detected line.
+ sr.ReadLine(); // Skip over it
+ else
+ titles.Add(Parse(sr));
+ }
+
+ return titles.ToArray();
+ }
+
+ /// <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()
+ {
+ return string.Format("{0} ({1:00}:{2:00}:{3:00})", TitleNumber, Duration.Hours, Duration.Minutes, Duration.Seconds);
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Properties/AssemblyInfo.cs.tmpl b/win/CS/HandBrake.ApplicationServices/Properties/AssemblyInfo.cs.tmpl
new file mode 100644
index 000000000..5669415aa
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Properties/AssemblyInfo.cs.tmpl
@@ -0,0 +1,42 @@
+/* AssemblyInfo.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HandBrake")]
+[assembly: AssemblyDescription("HandBrake is a GPL-licensed, multiplatform, multithreaded video transcoder.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HandBrake Team")]
+[assembly: AssemblyProduct("HandBrake")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("5e4e3f97-5252-41f6-aae9-3846f62cbc66")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("0.9.5.$WCREV$")]
+[assembly: NeutralResourcesLanguage("")]
diff --git a/win/CS/HandBrake.ApplicationServices/Properties/Resources.Designer.cs b/win/CS/HandBrake.ApplicationServices/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..c1dd66e55
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Properties/Resources.Designer.cs
@@ -0,0 +1,70 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.1
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace HandBrake.ApplicationServices.Properties {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HandBrake.ApplicationServices.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ internal static System.Drawing.Bitmap logo64 {
+ get {
+ object obj = ResourceManager.GetObject("logo64", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Properties/Resources.resx b/win/CS/HandBrake.ApplicationServices/Properties/Resources.resx
new file mode 100644
index 000000000..2e1c2842b
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Properties/Resources.resx
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+ <data name="logo64" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>..\Resources\logo64.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Resources/logo64.png b/win/CS/HandBrake.ApplicationServices/Resources/logo64.png
new file mode 100644
index 000000000..12808f636
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Resources/logo64.png
Binary files differ
diff --git a/win/CS/HandBrake.ApplicationServices/Services/Encode.cs b/win/CS/HandBrake.ApplicationServices/Services/Encode.cs
new file mode 100644
index 000000000..4a6333da7
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/Encode.cs
@@ -0,0 +1,595 @@
+/* Encode.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Services
+{
+ using System;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Text;
+ using System.Threading;
+ using System.Windows.Forms;
+
+ using HandBrake.ApplicationServices.EventArgs;
+ using HandBrake.ApplicationServices.Functions;
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Parsing;
+ using HandBrake.ApplicationServices.Services.Interfaces;
+ using HandBrake.ApplicationServices.Utilities;
+
+ /// <summary>
+ /// Class which handles the CLI
+ /// </summary>
+ public class Encode : IEncode
+ {
+ #region Private Variables
+
+ /// <summary>
+ /// The Log Buffer
+ /// </summary>
+ private StringBuilder logBuffer;
+
+ /// <summary>
+ /// The Log file writer
+ /// </summary>
+ private StreamWriter fileWriter;
+
+ /// <summary>
+ /// Gets The Process Handle
+ /// </summary>
+ private IntPtr processHandle;
+
+ /// <summary>
+ /// Gets the Process ID
+ /// </summary>
+ private int processId;
+
+ /// <summary>
+ /// Windows 7 API Pack wrapper
+ /// </summary>
+ private Win7 windowsSeven = new Win7();
+
+ /// <summary>
+ /// A Lock for the filewriter
+ /// </summary>
+ static readonly object fileWriterLock = new object();
+
+ #endregion
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Encode"/> class.
+ /// </summary>
+ public Encode()
+ {
+ this.EncodeStarted += this.EncodeEncodeStarted;
+ GrowlCommunicator.Register();
+ }
+
+ #region Delegates and Event Handlers
+
+ /// <summary>
+ /// Fires when a new CLI QueueTask starts
+ /// </summary>
+ public event EventHandler EncodeStarted;
+
+ /// <summary>
+ /// Fires when a CLI QueueTask finishes.
+ /// </summary>
+ public event EncodeCompletedStatus EncodeCompleted;
+
+ /// <summary>
+ /// Encode process has progressed
+ /// </summary>
+ public event EncodeProgessStatus EncodeStatusChanged;
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets The HB Process
+ /// </summary>
+ protected Process HbProcess { get; set; }
+
+ /// <summary>
+ /// Gets a value indicating whether IsEncoding.
+ /// </summary>
+ public bool IsEncoding { get; private set; }
+
+ /// <summary>
+ /// Gets ActivityLog.
+ /// </summary>
+ public string ActivityLog
+ {
+ get
+ {
+ if (this.IsEncoding == false)
+ {
+ try
+ {
+ ReadFile(); // Read the last log file back in if it exists
+ }
+ catch (Exception exc)
+ {
+ return exc.ToString();
+ }
+ }
+
+ return string.IsNullOrEmpty(this.logBuffer.ToString()) ? "No log data available..." : this.logBuffer.ToString();
+ }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// Execute a HandBrakeCLI process.
+ /// </summary>
+ /// <param name="encodeQueueTask">
+ /// The encodeQueueTask.
+ /// </param>
+ /// <param name="enableLogging">
+ /// Enable Logging. When Disabled we onlt parse Standard Ouput for progress info. Standard Error log data is ignored.
+ /// </param>
+ public void Start(QueueTask encodeQueueTask, bool enableLogging)
+ {
+ try
+ {
+ QueueTask queueTask = encodeQueueTask;
+
+ if (queueTask == null)
+ {
+ throw new ArgumentNullException("QueueTask was null");
+ }
+
+ if (IsEncoding)
+ {
+ throw new Exception("HandBrake is already encodeing.");
+ }
+
+ IsEncoding = true;
+
+ if (enableLogging)
+ {
+ try
+ {
+ SetupLogging(queueTask);
+ }
+ catch (Exception)
+ {
+ IsEncoding = false;
+ throw;
+ }
+ }
+
+ if (Init.PreventSleep)
+ {
+ Win32.PreventSleep();
+ }
+
+ string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");
+ ProcessStartInfo cliStart = new ProcessStartInfo(handbrakeCLIPath, queueTask.Query)
+ {
+ RedirectStandardOutput = true,
+ RedirectStandardError = enableLogging ? true : false,
+ UseShellExecute = false,
+ CreateNoWindow = !Init.ShowCliForInGuiEncodeStatus ? true : false
+ };
+
+ this.HbProcess = new Process { StartInfo = cliStart };
+
+ this.HbProcess.Start();
+
+ if (enableLogging)
+ {
+ this.HbProcess.ErrorDataReceived += HbProcErrorDataReceived;
+ this.HbProcess.BeginErrorReadLine();
+ }
+
+ this.processId = HbProcess.Id;
+ this.processHandle = HbProcess.Handle;
+
+ // Set the process Priority
+ if (this.processId != -1)
+ {
+ this.HbProcess.EnableRaisingEvents = true;
+ this.HbProcess.Exited += this.HbProcessExited;
+ }
+
+ // Set the Process Priority
+ switch (Init.ProcessPriority)
+ {
+ case "Realtime":
+ this.HbProcess.PriorityClass = ProcessPriorityClass.RealTime;
+ break;
+ case "High":
+ this.HbProcess.PriorityClass = ProcessPriorityClass.High;
+ break;
+ case "Above Normal":
+ this.HbProcess.PriorityClass = ProcessPriorityClass.AboveNormal;
+ break;
+ case "Normal":
+ this.HbProcess.PriorityClass = ProcessPriorityClass.Normal;
+ break;
+ case "Low":
+ this.HbProcess.PriorityClass = ProcessPriorityClass.Idle;
+ break;
+ default:
+ this.HbProcess.PriorityClass = ProcessPriorityClass.BelowNormal;
+ break;
+ }
+
+ // Fire the Encode Started Event
+ if (this.EncodeStarted != null)
+ this.EncodeStarted(this, new EventArgs());
+ }
+ catch (Exception exc)
+ {
+ if (this.EncodeCompleted != null)
+ this.EncodeCompleted(this, new EncodeCompletedEventArgs(false, exc, "An Error has occured in EncodeService.Run()"));
+ }
+ }
+
+ /// <summary>
+ /// Stop the Encode
+ /// </summary>
+ public void Stop()
+ {
+ this.Stop(null);
+ }
+
+ /// <summary>
+ /// Kill the CLI process
+ /// </summary>
+ /// <param name="exc">
+ /// The Exception that has occured.
+ /// This will get bubbled up through the EncodeCompletedEventArgs
+ /// </param>
+ public void Stop(Exception exc)
+ {
+ try
+ {
+ if (this.HbProcess != null && !this.HbProcess.HasExited)
+ {
+ this.HbProcess.Kill();
+ }
+ }
+ catch (Exception)
+ {
+ // No need to report anything to the user. If it fails, it's probably already stopped.
+ }
+
+
+ if (exc == null)
+ {
+ if (this.EncodeCompleted != null)
+ this.EncodeCompleted(this, new EncodeCompletedEventArgs(true, null, string.Empty));
+ }
+ else
+ {
+ if (this.EncodeCompleted != null)
+ this.EncodeCompleted(this, new EncodeCompletedEventArgs(false, exc, "An Error has occured."));
+ }
+ }
+
+ /// <summary>
+ /// Attempt to Safely kill a DirectRun() CLI
+ /// NOTE: This will not work with a MinGW CLI
+ /// Note: http://www.cygwin.com/ml/cygwin/2006-03/msg00330.html
+ /// </summary>
+ public void SafelyStop()
+ {
+ if ((int)this.processHandle == 0)
+ return;
+
+ // Allow the CLI to exit cleanly
+ Win32.SetForegroundWindow((int)this.processHandle);
+ SendKeys.Send("^C");
+ SendKeys.Flush();
+
+ /*/if (HbProcess != null)
+ //{
+ // HbProcess.StandardInput.AutoFlush = true;
+ // HbProcess.StandardInput.WriteLine("^c^z");
+ //}*/
+ }
+
+ /// <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>
+ public void ProcessLogs(string destination)
+ {
+ try
+ {
+ string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
+ "\\HandBrake\\logs";
+ string tempLogFile = Path.Combine(logDir, string.Format("last_encode_log{0}.txt", Init.InstanceId));
+
+ 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 (Init.SaveLogWithVideo)
+ File.Copy(tempLogFile, Path.Combine(encodeDestinationPath, encodeLogFile));
+
+ // Save a copy of the log file to a user specified location
+ if (Directory.Exists(Init.SaveLogPath))
+ if (Init.SaveLogPath != String.Empty && Init.SaveLogToSpecifiedPath)
+ File.Copy(tempLogFile, Path.Combine(Init.SaveLogPath, encodeLogFile));
+ }
+ catch (Exception exc)
+ {
+ // This exception doesn't warrent user interaction, but it should be logged (TODO)
+ }
+ }
+
+ #endregion
+
+ #region Private Helper Methods
+
+ /// <summary>
+ /// The HandBrakeCLI process has exited.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The EventArgs.
+ /// </param>
+ private void HbProcessExited(object sender, EventArgs e)
+ {
+ IsEncoding = false;
+ if (windowsSeven.IsWindowsSeven)
+ {
+ windowsSeven.SetTaskBarProgressToNoProgress();
+ }
+
+ if (Init.PreventSleep)
+ {
+ Win32.AllowSleep();
+ }
+
+ try
+ {
+ lock (fileWriterLock)
+ {
+ // This is just a quick hack to ensure that we are done processing the logging data.
+ // Logging data comes in after the exit event has processed sometimes. We should really impliment ISyncronizingInvoke
+ // and set the SyncObject on the process. I think this may resolve this properly.
+ // For now, just wait 2.5 seconds to let any trailing log messages come in and be processed.
+ Thread.Sleep(2500);
+
+ this.HbProcess.CancelErrorRead();
+
+ if (fileWriter != null)
+ {
+ fileWriter.Close();
+ fileWriter.Dispose();
+ }
+
+ fileWriter = null;
+ }
+ }
+ catch (Exception exc)
+ {
+ // This exception doesn't warrent user interaction, but it should be logged (TODO)
+ }
+
+ if (this.EncodeCompleted != null)
+ this.EncodeCompleted(this, new EncodeCompletedEventArgs(true, null, string.Empty));
+ }
+
+ /// <summary>
+ /// Read the log file
+ /// </summary>
+ private void ReadFile()
+ {
+ logBuffer = new StringBuilder();
+ lock (logBuffer)
+ {
+ // last_encode_log.txt is the primary log file. Since .NET can't read this file whilst the CLI is outputing to it (Not even in read only mode),
+ // we'll need to make a copy of it.
+ string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
+ string logFile = Path.Combine(logDir, string.Format("last_encode_log{0}.txt", Init.InstanceId));
+ string logFile2 = Path.Combine(logDir, string.Format("tmp_appReadable_log{0}.txt", Init.InstanceId));
+ int logFilePosition = 0;
+
+ try
+ {
+ // Copy the log file.
+ if (File.Exists(logFile))
+ File.Copy(logFile, logFile2, true);
+ else
+ return;
+
+ // Start the Reader
+ // Only use text which continues on from the last read line
+ using (StreamReader sr = new StreamReader(logFile2))
+ {
+ string line;
+ int i = 1;
+ while ((line = sr.ReadLine()) != null)
+ {
+ if (i > logFilePosition)
+ {
+ logBuffer.AppendLine(line);
+ logFilePosition++;
+ }
+ i++;
+ }
+ sr.Close();
+ }
+ }
+ catch (Exception exc)
+ {
+ logBuffer.Append(
+ Environment.NewLine + "Unable to read Log file..." + Environment.NewLine + exc +
+ Environment.NewLine);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Setup the logging.
+ /// </summary>
+ /// <param name="encodeQueueTask">
+ /// The encode QueueTask.
+ /// </param>
+ private void SetupLogging(QueueTask encodeQueueTask)
+ {
+ string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
+ string logFile = Path.Combine(logDir, string.Format("last_encode_log{0}.txt", Init.InstanceId));
+ string logFile2 = Path.Combine(logDir, string.Format("tmp_appReadable_log{0}.txt", Init.InstanceId));
+
+ try
+ {
+ logBuffer = new StringBuilder();
+
+ // Clear the current Encode Logs
+ if (File.Exists(logFile)) File.Delete(logFile);
+ if (File.Exists(logFile2)) File.Delete(logFile2);
+
+ fileWriter = new StreamWriter(logFile) { AutoFlush = true };
+
+ fileWriter.WriteLine(UtilityService.CreateCliLogHeader(encodeQueueTask));
+ logBuffer.AppendLine(UtilityService.CreateCliLogHeader(encodeQueueTask));
+ }
+ catch (Exception)
+ {
+ if (fileWriter != null)
+ {
+ fileWriter.Close();
+ fileWriter.Dispose();
+ }
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// Recieve the Standard Error information and process it
+ /// </summary>
+ /// <param name="sender">
+ /// The Sender Object
+ /// </param>
+ /// <param name="e">
+ /// DataReceived EventArgs
+ /// </param>
+ private void HbProcErrorDataReceived(object sender, DataReceivedEventArgs e)
+ {
+ if (!String.IsNullOrEmpty(e.Data))
+ {
+ try
+ {
+ lock (logBuffer)
+ logBuffer.AppendLine(e.Data);
+
+ lock (fileWriterLock)
+ {
+ if (fileWriter != null && fileWriter.BaseStream.CanWrite)
+ {
+ fileWriter.WriteLine(e.Data);
+
+ // If the logging grows past 100MB, kill the encode and stop.
+ if (fileWriter.BaseStream.Length > 100000000)
+ {
+ this.Stop(
+ new Exception(
+ "The encode has been stopped. The log file has grown to over 100MB which indicates a serious problem has occured with the encode." +
+ "Please check the encode log for an indication of what the problem is."));
+ }
+ }
+ }
+ }
+ catch (Exception exc)
+ {
+ // Do Nothing.
+ }
+ }
+ }
+
+ /// <summary>
+ /// Encode Started
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The EventArgs.
+ /// </param>
+ private void EncodeEncodeStarted(object sender, EventArgs e)
+ {
+ Thread monitor = new Thread(EncodeMonitor);
+ monitor.Start();
+ }
+
+ /// <summary>
+ /// Monitor the QueueTask
+ /// </summary>
+ private void EncodeMonitor()
+ {
+ try
+ {
+ Parser encode = new Parser(HbProcess.StandardOutput.BaseStream);
+ encode.OnEncodeProgress += EncodeOnEncodeProgress;
+ while (!encode.EndOfStream)
+ encode.ReadEncodeStatus();
+ }
+ catch (Exception exc)
+ {
+ EncodeOnEncodeProgress(null, 0, 0, 0, 0, 0, "Unknown, status not available..");
+ }
+ }
+
+ /// <summary>
+ /// Displays the Encode status in the GUI
+ /// </summary>
+ /// <param name="sender">The sender</param>
+ /// <param name="currentTask">The current task</param>
+ /// <param name="taskCount">Number of tasks</param>
+ /// <param name="percentComplete">Percent complete</param>
+ /// <param name="currentFps">Current encode speed in fps</param>
+ /// <param name="avg">Avg encode speed</param>
+ /// <param name="timeRemaining">Time Left</param>
+ private void EncodeOnEncodeProgress(object sender, int currentTask, int taskCount, float percentComplete, float currentFps, float avg, string timeRemaining)
+ {
+ EncodeProgressEventArgs eventArgs = new EncodeProgressEventArgs
+ {
+ AverageFrameRate = avg,
+ CurrentFrameRate = currentFps,
+ EstimatedTimeLeft = Converters.EncodeToTimespan(timeRemaining),
+ PercentComplete = percentComplete,
+ Task = currentTask,
+ TaskCount = taskCount
+ };
+
+ if (this.EncodeStatusChanged != null)
+ this.EncodeStatusChanged(this, eventArgs);
+
+ if (windowsSeven.IsWindowsSeven)
+ {
+ int percent;
+ int.TryParse(Math.Round(percentComplete).ToString(), out percent);
+
+ windowsSeven.SetTaskBarProgress(percent);
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IEncode.cs b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IEncode.cs
new file mode 100644
index 000000000..7ba739617
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IEncode.cs
@@ -0,0 +1,96 @@
+/* IEncode.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Services.Interfaces
+{
+ using System;
+
+ using HandBrake.ApplicationServices.EventArgs;
+ using HandBrake.ApplicationServices.Model;
+
+ /// <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 CLI Job starts
+ /// </summary>
+ event EventHandler EncodeStarted;
+
+ /// <summary>
+ /// Fires when a CLI 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>
+ /// Start with a LibHb EncodeJob Object
+ /// </summary>
+ /// <param name="job">
+ /// The job.
+ /// </param>
+ /// <param name="enableLogging">
+ /// The enable Logging.
+ /// </param>
+ void Start(QueueTask job, bool enableLogging);
+
+ /// <summary>
+ /// Kill the CLI process
+ /// </summary>
+ void Stop();
+
+ /// <summary>
+ /// Attempt to Safely kill a DirectRun() CLI
+ /// NOTE: This will not work with a MinGW CLI
+ /// Note: http://www.cygwin.com/ml/cygwin/2006-03/msg00330.html
+ /// </summary>
+ void SafelyStop();
+
+ /// <summary>
+ /// Copy the log file to the desired destinations
+ /// </summary>
+ /// <param name="destination">
+ /// The destination.
+ /// </param>
+ void ProcessLogs(string destination);
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IPresetService.cs b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IPresetService.cs
new file mode 100644
index 000000000..30d6b2f3a
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IPresetService.cs
@@ -0,0 +1,93 @@
+/* IPresetService.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Services.Interfaces
+{
+ using System.Collections.ObjectModel;
+
+ using HandBrake.ApplicationServices.Model;
+
+ /// <summary>
+ /// The Preset Service Interface
+ /// </summary>
+ public interface IPresetService
+ {
+ /// <summary>
+ /// Gets or sets a Collection of presets.
+ /// </summary>
+ ObservableCollection<Preset> Presets { get; set; }
+
+ /// <summary>
+ /// Add a new preset to the system
+ /// </summary>
+ /// <param name="preset">
+ /// A Preset to add
+ /// </param>
+ /// <returns>
+ /// True if added,
+ /// False if name already exists
+ /// </returns>
+ bool Add(Preset preset);
+
+ /// <summary>
+ /// Remove a preset with a given name from either the built in or user preset list.
+ /// </summary>
+ /// <param name="preset">
+ /// The Preset to remove
+ /// </param>
+ void Remove(Preset preset);
+
+ /// <summary>
+ /// Remove a group of presets by category
+ /// </summary>
+ /// <param name="category">
+ /// The Category to remove
+ /// </param>
+ void RemoveGroup(string category);
+
+ /// <summary>
+ /// Get a Preset
+ /// </summary>
+ /// <param name="name">
+ /// The name of the preset to get
+ /// </param>
+ /// <returns>
+ /// A Preset or null object
+ /// </returns>
+ Preset GetPreset(string name);
+
+ /// <summary>
+ /// Clear Built-in Presets
+ /// </summary>
+ void ClearBuiltIn();
+
+ /// <summary>
+ /// Clear all presets
+ /// </summary>
+ void ClearAll();
+
+ /// <summary>
+ /// Reads the CLI's CLI output format and load's them into the preset List Preset
+ /// </summary>
+ /// <param name="cliPath">
+ /// The Path to the CLI, leave blank for current folder.
+ /// </param>
+ void UpdateBuiltInPresets(string cliPath);
+
+ /// <summary>
+ /// Check if the built in Presets stored are not out of date.
+ /// Update them if they are.
+ /// </summary>
+ /// <returns>true if out of date</returns>
+ bool CheckIfPresetsAreOutOfDate();
+
+ /// <summary>
+ /// Check if the preset "name" exists in either Presets or UserPresets lists.
+ /// </summary>
+ /// <param name="name">Name of the preset</param>
+ /// <returns>True if found</returns>
+ bool CheckIfPresetExists(string name);
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueManager.cs b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueManager.cs
new file mode 100644
index 000000000..2c9005cfb
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueManager.cs
@@ -0,0 +1,113 @@
+/* IQueueManager.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Services.Interfaces
+{
+ using System;
+ using System.Collections.ObjectModel;
+
+ using HandBrake.ApplicationServices.Model;
+
+ /// <summary>
+ /// The Queue Manager Interface
+ /// </summary>
+ public interface IQueueManager
+ {
+ /// <summary>
+ /// Fires when a job is Added, Removed or Re-Ordered.
+ /// Should be used for triggering an update of the Queue Window.
+ /// </summary>
+ event EventHandler QueueChanged;
+
+ /// <summary>
+ /// Gets or sets Last Processed Job.
+ /// This is set when the job is poped of the queue by GetNextJobForProcessing();
+ /// </summary>
+ QueueTask LastProcessedJob { get; set; }
+
+ /// <summary>
+ /// Gets The current queue.
+ /// </summary>
+ ReadOnlyCollection<QueueTask> Queue { get; }
+
+ /// <summary>
+ /// Gets the number of jobs in the queue
+ /// </summary>
+ int Count { get; }
+
+ /// <summary>
+ /// Add a job to the Queue.
+ /// This method is Thread Safe.
+ /// </summary>
+ /// <param name="job">
+ /// The encode Job object.
+ /// </param>
+ void Add(QueueTask job);
+
+ /// <summary>
+ /// Remove a job from the Queue.
+ /// This method is Thread Safe
+ /// </summary>
+ /// <param name="job">
+ /// The job.
+ /// </param>
+ void Remove(QueueTask job);
+
+ /// <summary>
+ /// Get the first job on the queue for processing.
+ /// This also removes the job from the Queue and sets the LastProcessedJob
+ /// </summary>
+ /// <returns>
+ /// An encode Job object.
+ /// </returns>
+ QueueTask GetNextJobForProcessing();
+
+ /// <summary>
+ /// Moves an item up one position in the queue.
+ /// </summary>
+ /// <param name="index">The zero-based location of the job in the queue.</param>
+ void MoveUp(int index);
+
+ /// <summary>
+ /// Moves an item down one position in the queue.
+ /// </summary>
+ /// <param name="index">The zero-based location of the job in the queue.</param>
+ void MoveDown(int index);
+
+ /// <summary>
+ /// Backup any changes to the queue file
+ /// </summary>
+ /// <param name="exportPath">
+ /// If this is not null or empty, this will be used instead of the standard backup location.
+ /// </param>
+ void BackupQueue(string exportPath);
+
+ /// <summary>
+ /// Restore a Queue from file or from the queue backup file.
+ /// </summary>
+ /// <param name="importPath">
+ /// The import path. String.Empty or null will result in the default file being loaded.
+ /// </param>
+ void RestoreQueue(string importPath);
+
+ /// <summary>
+ /// Checks the current queue for an existing instance of the specified destination.
+ /// </summary>
+ /// <param name="destination">The destination of the encode.</param>
+ /// <returns>Whether or not the supplied destination is already in the queue.</returns>
+ bool CheckForDestinationPathDuplicates(string destination);
+
+ /// <summary>
+ /// Create a batch script from the queue
+ /// </summary>
+ /// <param name="path">
+ /// The path to the location for the script to be saved.
+ /// </param>
+ /// <returns>
+ /// True if sucessful
+ /// </returns>
+ bool WriteBatchScriptToFile(string path);
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueProcessor.cs b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueProcessor.cs
new file mode 100644
index 000000000..3d71688cb
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueProcessor.cs
@@ -0,0 +1,51 @@
+namespace HandBrake.ApplicationServices.Services.Interfaces
+{
+ using System;
+
+ /// <summary>
+ /// The Queue Processor
+ /// </summary>
+ public interface IQueueProcessor
+ {
+ /// <summary>
+ /// Fires when the Queue has started
+ /// </summary>
+ event QueueProcessor.QueueProgressStatus JobProcessingStarted;
+
+ /// <summary>
+ /// Fires when a pause to the encode queue has been requested.
+ /// </summary>
+ event EventHandler QueuePaused;
+
+ /// <summary>
+ /// Fires when the entire encode queue has completed.
+ /// </summary>
+ event EventHandler QueueCompleted;
+
+ /// <summary>
+ /// Gets the IEncodeService instance.
+ /// </summary>
+ IEncode EncodeService { get; }
+
+ /// <summary>
+ /// Gets the IQueueManager instance.
+ /// </summary>
+ IQueueManager QueueManager { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether IsProcessing.
+ /// </summary>
+ bool IsProcessing { get; }
+
+ /// <summary>
+ /// Starts encoding the first job in the queue and continues encoding until all jobs
+ /// have been encoded.
+ /// </summary>
+ void Start();
+
+ /// <summary>
+ /// Requests a pause of the encode queue.
+ /// </summary>
+ void Pause();
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IScan.cs b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IScan.cs
new file mode 100644
index 000000000..6cbce5273
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IScan.cs
@@ -0,0 +1,83 @@
+/* IScan.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Services.Interfaces
+{
+ using System;
+
+ using HandBrake.ApplicationServices.EventArgs;
+ using HandBrake.ApplicationServices.Parsing;
+
+ /// <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 ScanStared;
+
+ /// <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 the Souce Data.
+ /// </summary>
+ Source SouceData { 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>
+ void Scan(string sourcePath, int title);
+
+ /// <summary>
+ /// Kill the scan
+ /// </summary>
+ void Stop();
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Services/LibScan.cs b/win/CS/HandBrake.ApplicationServices/Services/LibScan.cs
new file mode 100644
index 000000000..6f200e447
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/LibScan.cs
@@ -0,0 +1,328 @@
+/* LibScan.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Services
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Threading;
+
+ using HandBrake.ApplicationServices.EventArgs;
+ using HandBrake.ApplicationServices.Model.Encoding;
+ using HandBrake.ApplicationServices.Parsing;
+ using HandBrake.ApplicationServices.Services.Interfaces;
+ using HandBrake.Interop;
+
+ using AudioTrack = HandBrake.ApplicationServices.Parsing.AudioTrack;
+ using Cropping = HandBrake.ApplicationServices.Model.Encoding.Cropping;
+ using ScanProgressEventArgs = HandBrake.Interop.ScanProgressEventArgs;
+ using Size = System.Drawing.Size;
+
+ /// <summary>
+ /// Scan a Source
+ /// </summary>
+ public class LibScan : IScan
+ {
+ /*
+ * TODO
+ * 1. Expose the Previews code.
+ * 2. Expose the Logging.
+ *
+ */
+
+ #region Private Variables
+
+ /// <summary>
+ /// Lock for the log file
+ /// </summary>
+ static readonly object LogLock = new object();
+
+ /// <summary>
+ /// LibHB Instance
+ /// </summary>
+ private readonly HandBrakeInstance instance;
+
+ /// <summary>
+ /// Log data from HandBrakeInstance
+ /// </summary>
+ private readonly StringBuilder logging;
+
+ #endregion
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="LibScan"/> class.
+ /// </summary>
+ public LibScan()
+ {
+ logging = new StringBuilder();
+
+ instance = new HandBrakeInstance();
+ instance.Initialize(1);
+ instance.ScanProgress += this.InstanceScanProgress;
+ instance.ScanCompleted += this.InstanceScanCompleted;
+
+ HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged;
+ HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged;
+ }
+
+ #region Events
+
+ /// <summary>
+ /// Scan has Started
+ /// </summary>
+ public event EventHandler ScanStared;
+
+ /// <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 the Souce Data.
+ /// </summary>
+ public Source SouceData { get; private set; }
+
+ /// <summary>
+ /// Gets ActivityLog.
+ /// </summary>
+ public string ActivityLog
+ {
+ get
+ {
+ return 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>
+ public void Scan(string sourcePath, int title)
+ {
+ Thread t = new Thread(unused => this.ScanSource(sourcePath, title));
+ t.Start();
+ }
+
+ /// <summary>
+ /// Kill the scan
+ /// </summary>
+ public void Stop()
+ {
+ instance.StopScan();
+ }
+
+ #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>
+ private void ScanSource(object sourcePath, int title)
+ {
+ try
+ {
+ IsScanning = true;
+ if (this.ScanStared != null)
+ this.ScanStared(this, new EventArgs());
+
+ if (title != 0)
+ instance.StartScan(sourcePath.ToString(), 10, title);
+ else
+ instance.StartScan(sourcePath.ToString(), 10);
+ }
+ catch (Exception exc)
+ {
+ this.Stop();
+
+ if (this.ScanCompleted != null)
+ this.ScanCompleted(this, new ScanCompletedEventArgs(false, exc, "An Error has occured in ScanService.ScanSource()"));
+ }
+ }
+
+ #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, EventArgs e)
+ {
+ this.SouceData = new Source { Titles = ConvertTitles(this.instance.Titles) };
+
+ IsScanning = false;
+
+ if (this.ScanCompleted != null)
+ this.ScanCompleted(this, new ScanCompletedEventArgs(true, null, string.Empty));
+ }
+
+ /// <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)
+ {
+ ApplicationServices.EventArgs.ScanProgressEventArgs eventArgs =
+ new ApplicationServices.EventArgs.ScanProgressEventArgs
+ {
+ CurrentTitle = e.CurrentTitle,
+ Titles = e.Titles
+ };
+
+ 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)
+ {
+ lock (LogLock)
+ {
+ this.logging.AppendLine(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.logging.AppendLine(e.Message);
+ }
+ }
+
+ /// <summary>
+ /// Convert Interop Title objects to App Services Title object
+ /// </summary>
+ /// <param name="titles">
+ /// The titles.
+ /// </param>
+ /// <returns>
+ /// The convert titles.
+ /// </returns>
+ private static List<Title> ConvertTitles(IEnumerable<SourceData.Title> titles)
+ {
+ List<Title> titleList = new List<Title>();
+ foreach (SourceData.Title title in titles)
+ {
+ Title converted = new Title
+ {
+ TitleNumber = title.TitleNumber,
+ Duration = title.Duration,
+ Resolution = new Size(title.Resolution.Width, title.Resolution.Height),
+ AspectRatio = title.AspectRatio,
+ AngleCount = title.AngleCount,
+ ParVal = new Size(title.ParVal.Width, title.ParVal.Height),
+ AutoCropDimensions =
+ new Cropping(
+ title.AutoCropDimensions.Top,
+ title.AutoCropDimensions.Bottom,
+ title.AutoCropDimensions.Left,
+ title.AutoCropDimensions.Right),
+ Fps = title.Framerate
+ };
+
+ foreach (SourceData.Chapter chapter in title.Chapters)
+ {
+ converted.Chapters.Add(new Chapter(chapter.ChapterNumber, string.Empty, chapter.Duration));
+ }
+
+ foreach (SourceData.AudioTrack track in title.AudioTracks)
+ {
+ converted.AudioTracks.Add(new AudioTrack(track.TrackNumber, track.Language, track.LanguageCode, track.Description, string.Empty, track.SampleRate, track.Bitrate));
+ }
+
+ foreach (SourceData.Subtitle track in title.Subtitles)
+ {
+ SubtitleType convertedType = new SubtitleType();
+
+ switch (track.SubtitleSource)
+ {
+ case SourceData.SubtitleSource.VobSub:
+ convertedType = SubtitleType.VobSub;
+ break;
+ case SourceData.SubtitleSource.UTF8:
+ convertedType = SubtitleType.UTF8Sub;
+ break;
+ case SourceData.SubtitleSource.TX3G:
+ convertedType = SubtitleType.TX3G;
+ break;
+ case SourceData.SubtitleSource.SSA:
+ convertedType = SubtitleType.SSA;
+ break;
+ case SourceData.SubtitleSource.SRT:
+ convertedType = SubtitleType.SRT;
+ break;
+ case SourceData.SubtitleSource.CC608:
+ convertedType = SubtitleType.CC;
+ break;
+ case SourceData.SubtitleSource.CC708:
+ convertedType = SubtitleType.CC;
+ break;
+ }
+
+ converted.Subtitles.Add(new Subtitle(track.TrackNumber, track.Language, track.LanguageCode, convertedType));
+ }
+
+ titleList.Add(converted);
+ }
+
+ return titleList;
+ }
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Services/PresetService.cs b/win/CS/HandBrake.ApplicationServices/Services/PresetService.cs
new file mode 100644
index 000000000..f46a8bad1
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/PresetService.cs
@@ -0,0 +1,403 @@
+/* PresetService.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Services
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Linq;
+ using System.Text.RegularExpressions;
+ using System.Windows.Data;
+ using System.Xml.Serialization;
+
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Services.Interfaces;
+
+ /// <summary>
+ /// The preset service manages HandBrake's presets
+ /// </summary>
+ public class PresetService : IPresetService
+ {
+ /**
+ * TODO:
+ * - Wire this into the Forms and WPF UI's
+ * - Note: This is untested so far. It'll likely need fixes before it can be used.
+ * - Maybe change the collection to a dictionary to allow easier lookups?
+ **/
+
+ #region Private Variables
+
+ /// <summary>
+ /// XML Serializer
+ /// </summary>
+ private static readonly XmlSerializer Ser = new XmlSerializer(typeof(List<Preset>));
+
+ /// <summary>
+ /// The User Preset file
+ /// </summary>
+ private readonly string userPresetFile = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\user_presets.xml";
+
+ /// <summary>
+ /// The Built In Presets File
+ /// </summary>
+ private readonly string builtInPresetFile = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\presets.xml";
+
+ /// <summary>
+ /// A Collection of presets
+ /// </summary>
+ private ObservableCollection<Preset> presets = new ObservableCollection<Preset>();
+
+ #endregion
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PresetService"/> class.
+ /// </summary>
+ public PresetService()
+ {
+ // this.Presets = CollectionViewSource.GetDefaultView(this.presets);
+ this.LoadPresets();
+ }
+
+ /// <summary>
+ /// Gets or sets a Collection of presets.
+ /// </summary>
+ public ObservableCollection<Preset> Presets
+ {
+ get
+ {
+ return this.presets;
+ }
+
+ set
+ {
+ this.presets = value;
+ }
+ }
+
+ /// <summary>
+ /// The last preset added.
+ /// </summary>
+ public Preset LastPresetAdded { get; set; }
+
+ #region Public Methods
+
+ /// <summary>
+ /// Add a new preset to the system
+ /// </summary>
+ /// <param name="preset">
+ /// A Preset to add
+ /// </param>
+ /// <returns>
+ /// True if added,
+ /// False if name already exists
+ /// </returns>
+ public bool Add(Preset preset)
+ {
+ if (this.CheckIfPresetExists(preset.Name) == false)
+ {
+ this.presets.Add(preset);
+ this.LastPresetAdded = preset;
+
+ // Update the presets file
+ this.UpdatePresetFiles();
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Update a preset
+ /// </summary>
+ /// <param name="update">
+ /// The updated preset
+ /// </param>
+ public void Update(Preset update)
+ {
+ // TODO - Change this to be a lookup
+ foreach (Preset preset in this.presets)
+ {
+ if (preset.Name == update.Name)
+ {
+ preset.Query = update.Query;
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Remove a preset with a given name from either the built in or user preset list.
+ /// </summary>
+ /// <param name="preset">
+ /// The Preset to remove
+ /// </param>
+ public void Remove(Preset preset)
+ {
+ this.presets.Remove(preset);
+ this.UpdatePresetFiles();
+ }
+
+ /// <summary>
+ /// Remove a group of presets by category
+ /// </summary>
+ /// <param name="category">
+ /// The Category to remove
+ /// </param>
+ public void RemoveGroup(string category)
+ {
+ List<Preset> removeList = this.presets.Where(p => p.Category == category).ToList();
+ foreach (Preset preset in removeList)
+ {
+ this.presets.Remove(preset);
+ }
+
+ this.UpdatePresetFiles();
+ }
+
+ /// <summary>
+ /// Get a Preset
+ /// </summary>
+ /// <param name="name">
+ /// The name of the preset to get
+ /// </param>
+ /// <returns>
+ /// A Preset or null object
+ /// </returns>
+ public Preset GetPreset(string name)
+ {
+ return this.presets.FirstOrDefault(item => item.Name == name);
+ }
+
+ /// <summary>
+ /// Clear Built-in Presets
+ /// </summary>
+ public void ClearBuiltIn()
+ {
+ List<Preset> remove = this.presets.Where(p => p.IsBuildIn).ToList();
+ foreach (Preset preset in remove)
+ {
+ this.presets.Remove(preset);
+ }
+ }
+
+ /// <summary>
+ /// Clear all presets
+ /// </summary>
+ public void ClearAll()
+ {
+ this.presets.Clear();
+ }
+
+ /// <summary>
+ /// Reads the CLI's CLI output format and load's them into the preset List Preset
+ /// </summary>
+ /// <param name="cliPath">
+ /// The Path to the CLI, leave blank for current folder.
+ /// </param>
+ public void UpdateBuiltInPresets(string cliPath)
+ {
+ // Create a new tempory file and execute the CLI to get the built in Presets.
+ string handbrakeCLIPath = Path.Combine(cliPath, "HandBrakeCLI.exe");
+ string presetsPath = Path.Combine(Path.GetTempPath(), "temp_presets.dat");
+ string strCmdLine = String.Format(@"cmd /c """"{0}"" --preset-list >""{1}"" 2>&1""", handbrakeCLIPath, presetsPath);
+
+ ProcessStartInfo getPresets = new ProcessStartInfo("CMD.exe", strCmdLine) { WindowStyle = ProcessWindowStyle.Hidden };
+
+ Process hbproc = Process.Start(getPresets);
+ hbproc.WaitForExit();
+ hbproc.Dispose();
+ hbproc.Close();
+
+ // Clear the current built in Presets and now parse the tempory Presets file.
+ this.ClearBuiltIn();
+
+ if (File.Exists(presetsPath))
+ {
+ StreamReader presetInput = new StreamReader(presetsPath);
+
+ string category = String.Empty;
+
+ while (!presetInput.EndOfStream)
+ {
+ string line = presetInput.ReadLine();
+
+ // Found the beginning of a preset block
+ if (line != null && line.Contains("<") && !line.Contains("<<"))
+ {
+ category = line.Replace("<", string.Empty).Trim();
+ }
+
+ // Found a preset
+ if (line != null && line.Contains("+"))
+ {
+ Regex r = new Regex("(: )"); // Split on hyphens.
+ string[] presetName = r.Split(line);
+
+ bool pic = false;
+ if (presetName[2].Contains("crop"))
+ {
+ pic = true;
+ }
+
+ Preset newPreset = new Preset
+ {
+ Category = category,
+ Name = presetName[0].Replace("+", string.Empty).Trim(),
+ Query = presetName[2],
+ Version = Init.Version,
+ CropSettings = pic,
+ Description = string.Empty, // Maybe one day we will populate this.
+ IsBuildIn = true
+ };
+ this.presets.Add(newPreset);
+ }
+ }
+ presetInput.Close();
+ presetInput.Dispose();
+ }
+
+ // Finally, Create a new or update the current Presets.xml file
+ this.UpdatePresetFiles();
+ }
+
+ /// <summary>
+ /// Check if the built in Presets stored are not out of date.
+ /// Update them if they are.
+ /// </summary>
+ /// <returns>true if out of date</returns>
+ public bool CheckIfPresetsAreOutOfDate()
+ {
+ // Update built-in Presets if the built-in Presets belong to an older version.
+ if (this.presets.Count != 0)
+ {
+ if (this.presets[0].Version != Init.Version)
+ {
+ this.UpdateBuiltInPresets(string.Empty);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Check if the preset "name" exists in either Presets or UserPresets lists.
+ /// </summary>
+ /// <param name="name">Name of the preset</param>
+ /// <returns>True if found</returns>
+ public bool CheckIfPresetExists(string name)
+ {
+ return name == string.Empty || this.presets.Any(item => item.Name == name);
+ }
+
+ #endregion
+
+ #region Private Helpers
+
+ /// <summary>
+ /// Recover from a courrpted preset file
+ /// Add .old to the current filename, and delete the current file.
+ /// </summary>
+ /// <param name="file">
+ /// The broken presets file.
+ /// </param>
+ private static void RecoverFromCorruptedPresetFile(string file)
+ {
+ // Recover from Error.
+ if (File.Exists(file))
+ {
+ string disabledFile = file + ".old";
+ File.Move(file, disabledFile);
+ if (File.Exists(file))
+ {
+ File.Delete(file);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Load in the Built-in and User presets into the collection
+ /// </summary>
+ private void LoadPresets()
+ {
+ // First clear the Presets arraylists
+ this.presets.Clear();
+
+ // Load in the users Presets from UserPresets.xml
+ try
+ {
+ if (File.Exists(this.builtInPresetFile))
+ {
+ StreamReader reader = new StreamReader(this.builtInPresetFile);
+ List<Preset> list = (List<Preset>)Ser.Deserialize(reader);
+ foreach (Preset preset in list)
+ {
+ this.presets.Add(preset);
+ }
+
+ reader.Close();
+ }
+ }
+ catch (Exception)
+ {
+ RecoverFromCorruptedPresetFile(this.builtInPresetFile);
+ this.UpdateBuiltInPresets(string.Empty);
+ }
+
+ // Load in the users Presets from UserPresets.xml
+ try
+ {
+ if (File.Exists(this.userPresetFile))
+ {
+ StreamReader reader = new StreamReader(this.userPresetFile);
+ List<Preset> list = (List<Preset>)Ser.Deserialize(reader);
+ foreach (Preset preset in list)
+ {
+ this.presets.Add(preset);
+ }
+
+ reader.Close();
+ }
+ }
+ catch (Exception)
+ {
+ RecoverFromCorruptedPresetFile(this.userPresetFile);
+ }
+ }
+
+ /// <summary>
+ /// Update the preset files
+ /// </summary>
+ private void UpdatePresetFiles()
+ {
+ try
+ {
+ using (FileStream strm = new FileStream(this.builtInPresetFile, FileMode.Create, FileAccess.Write))
+ {
+ Ser.Serialize(strm, this.presets.Where(p => p.IsBuildIn).ToList());
+ strm.Close();
+ strm.Dispose();
+ }
+
+ using (FileStream strm = new FileStream(this.userPresetFile, FileMode.Create, FileAccess.Write))
+ {
+ Ser.Serialize(strm, this.presets.Where(p => p.IsBuildIn == false).ToList());
+ strm.Close();
+ strm.Dispose();
+ }
+ }
+ catch (Exception exc)
+ {
+ throw new Exception("Unable to write to the file. Please make sure the location has the correct permissions for file writing.\n Error Information: \n\n", exc);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Services/QueueManager.cs b/win/CS/HandBrake.ApplicationServices/Services/QueueManager.cs
new file mode 100644
index 000000000..7f723b8b4
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/QueueManager.cs
@@ -0,0 +1,340 @@
+/* QueueManager.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Services
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.IO;
+ using System.Linq;
+ using System.Windows.Forms;
+ using System.Xml.Serialization;
+
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Services.Interfaces;
+
+ using EventArgs = System.EventArgs;
+
+ /// <summary>
+ /// The Queue Manager.
+ /// Thread Safe.
+ /// </summary>
+ public class QueueManager : IQueueManager
+ {
+ /*
+ * TODO
+ * - Rewrite the batch script generator.
+ * - QueueTask, switch everything to use the Task property, which is a model of all settings.
+ */
+
+ #region Private Variables
+
+ /// <summary>
+ /// A Lock object to maintain thread safety
+ /// </summary>
+ static readonly object QueueLock = new object();
+
+ /// <summary>
+ /// The Queue of Job objects
+ /// </summary>
+ private readonly List<QueueTask> queue = new List<QueueTask>();
+
+ /// <summary>
+ /// HandBrakes Queue file with a place holder for an extra string.
+ /// </summary>
+ private readonly string queueFile;
+
+ /// <summary>
+ /// The ID of the job last added
+ /// </summary>
+ private int lastJobId;
+
+ /// <summary>
+ /// The instance Id of this HandBrake instance.
+ /// </summary>
+ private int instanceId;
+
+ #endregion
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="QueueManager"/> class.
+ /// </summary>
+ /// <param name="instanceId">
+ /// The instance Id.
+ /// </param>
+ public QueueManager(int instanceId)
+ {
+ this.instanceId = instanceId;
+
+ // If this is the first instance, just use the main queue file, otherwise add the instance id to the filename.
+ this.queueFile = instanceId == 0 ? "hb_queue_recovery.xml" : string.Format("hb_queue_recovery{0}.xml", instanceId);
+ }
+
+ #region Events
+ /// <summary>
+ /// Fires when a job is Added, Removed or Re-Ordered.
+ /// Should be used for triggering an update of the Queue Window.
+ /// </summary>
+ public event EventHandler QueueChanged;
+
+ /// <summary>
+ /// Invoke the Queue Changed Event
+ /// </summary>
+ /// <param name="e">
+ /// The e.
+ /// </param>
+ private void InvokeQueueChanged(EventArgs e)
+ {
+ try
+ {
+ this.BackupQueue(string.Empty);
+ }
+ catch (Exception)
+ {
+ // Do Nothing.
+ }
+
+ EventHandler handler = this.QueueChanged;
+ if (handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ /// <summary>
+ /// Gets or sets Last Processed Job.
+ /// This is set when the job is poped of the queue by GetNextJobForProcessing();
+ /// </summary>
+ public QueueTask LastProcessedJob { get; set; }
+
+ /// <summary>
+ /// Gets the number of jobs in the queue;
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ return this.queue.Count;
+ }
+ }
+
+ /// <summary>
+ /// Gets The current queue.
+ /// </summary>
+ public ReadOnlyCollection<QueueTask> Queue
+ {
+ get
+ {
+ return this.queue.AsReadOnly();
+ }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// Add a job to the Queue.
+ /// This method is Thread Safe.
+ /// </summary>
+ /// <param name="job">
+ /// The encode Job object.
+ /// </param>
+ public void Add(QueueTask job)
+ {
+ lock (QueueLock)
+ {
+ // Tag the job with an ID
+ job.Id = lastJobId++;
+ queue.Add(job);
+ InvokeQueueChanged(EventArgs.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Remove a job from the Queue.
+ /// This method is Thread Safe
+ /// </summary>
+ /// <param name="job">
+ /// The job.
+ /// </param>
+ public void Remove(QueueTask job)
+ {
+ lock (QueueLock)
+ {
+ queue.Remove(job);
+ InvokeQueueChanged(EventArgs.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Get the first job on the queue for processing.
+ /// This also removes the job from the Queue and sets the LastProcessedJob
+ /// </summary>
+ /// <returns>
+ /// An encode Job object.
+ /// </returns>
+ public QueueTask GetNextJobForProcessing()
+ {
+ if (this.queue.Count > 0)
+ {
+ QueueTask job = this.queue[0];
+ this.LastProcessedJob = job;
+ this.Remove(job); // Remove the item which we are about to pass out.
+
+ return job;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Moves an item up one position in the queue.
+ /// </summary>
+ /// <param name="index">The zero-based location of the job in the queue.</param>
+ public void MoveUp(int index)
+ {
+ if (index > 0)
+ {
+ QueueTask item = queue[index];
+
+ queue.RemoveAt(index);
+ queue.Insert((index - 1), item);
+ }
+
+ this.InvokeQueueChanged(EventArgs.Empty);
+ }
+
+ /// <summary>
+ /// Moves an item down one position in the queue.
+ /// </summary>
+ /// <param name="index">The zero-based location of the job in the queue.</param>
+ public void MoveDown(int index)
+ {
+ if (index < this.queue.Count - 1)
+ {
+ QueueTask item = this.queue[index];
+
+ this.queue.RemoveAt(index);
+ this.queue.Insert((index + 1), item);
+ }
+
+ this.InvokeQueueChanged(EventArgs.Empty);
+ }
+
+ /// <summary>
+ /// Backup any changes to the queue file
+ /// </summary>
+ /// <param name="exportPath">
+ /// If this is not null or empty, this will be used instead of the standard backup location.
+ /// </param>
+ public void BackupQueue(string exportPath)
+ {
+ string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
+ string tempPath = !string.IsNullOrEmpty(exportPath) ? exportPath : appDataPath + string.Format(this.queueFile, string.Empty);
+
+ using (FileStream strm = new FileStream(tempPath, FileMode.Create, FileAccess.Write))
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(List<QueueTask>));
+ serializer.Serialize(strm, queue);
+ strm.Close();
+ strm.Dispose();
+ }
+ }
+
+ /// <summary>
+ /// Restore a Queue from file or from the queue backup file.
+ /// </summary>
+ /// <param name="importPath">
+ /// The import path. String.Empty or null will result in the default file being loaded.
+ /// </param>
+ public void RestoreQueue(string importPath)
+ {
+ string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
+ string tempPath = !string.IsNullOrEmpty(importPath) ? importPath : (appDataPath + string.Format(this.queueFile, string.Empty));
+
+ if (File.Exists(tempPath))
+ {
+ using (FileStream strm = new FileStream((!string.IsNullOrEmpty(importPath) ? importPath : tempPath), FileMode.Open, FileAccess.Read))
+ {
+ if (strm.Length != 0)
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(List<QueueTask>));
+
+ List<QueueTask> list = serializer.Deserialize(strm) as List<QueueTask>;
+
+ if (list != null)
+ foreach (QueueTask item in list)
+ this.queue.Add(item);
+
+ this.InvokeQueueChanged(EventArgs.Empty);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Checks the current queue for an existing instance of the specified destination.
+ /// </summary>
+ /// <param name="destination">The destination of the encode.</param>
+ /// <returns>Whether or not the supplied destination is already in the queue.</returns>
+ public bool CheckForDestinationPathDuplicates(string destination)
+ {
+ return this.queue.Any(checkItem => checkItem.Destination.Contains(destination.Replace("\\\\", "\\")));
+ }
+
+ /// <summary>
+ /// Writes the current state of the queue in the form of a batch (.bat) file.
+ /// </summary>
+ /// <param name="file">
+ /// The location of the file to write the batch file to.
+ /// </param>
+ /// <returns>
+ /// The write batch script to file.
+ /// </returns>
+ public bool WriteBatchScriptToFile(string file)
+ {
+ string queries = string.Empty;
+ foreach (QueueTask queueItem in this.queue)
+ {
+ string qItem = queueItem.Query;
+ string fullQuery = '"' + Application.StartupPath + "\\HandBrakeCLI.exe" + '"' + qItem;
+
+ if (queries == string.Empty)
+ queries = queries + fullQuery;
+ else
+ queries = queries + " && " + fullQuery;
+ }
+ string strCmdLine = queries;
+
+ if (file != string.Empty)
+ {
+ try
+ {
+ // Create a StreamWriter and open the file, Write the batch file query to the file and
+ // Close the stream
+ using (StreamWriter line = new StreamWriter(file))
+ {
+ line.WriteLine(strCmdLine);
+ }
+
+ return true;
+ }
+ catch (Exception exc)
+ {
+ throw new Exception("Unable to write to the file. Please make sure that the location has the correct permissions for file writing.", exc);
+ }
+ }
+ return false;
+ }
+
+ #endregion
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs b/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs
new file mode 100644
index 000000000..130e1fc46
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs
@@ -0,0 +1,279 @@
+/* Queue.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Services
+{
+ using System;
+ using System.Diagnostics;
+ using System.Windows.Forms;
+
+ using HandBrake.ApplicationServices.EventArgs;
+ using HandBrake.ApplicationServices.Functions;
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Services.Interfaces;
+
+ /// <summary>
+ /// The HandBrake Queue
+ /// </summary>
+ public class QueueProcessor : IQueueProcessor
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="QueueProcessor"/> class.
+ /// </summary>
+ /// <param name="queueManager">
+ /// The queue manager.
+ /// </param>
+ /// <param name="encodeService">
+ /// The encode Service.
+ /// </param>
+ /// <exception cref="ArgumentNullException">
+ /// </exception>
+ public QueueProcessor(IQueueManager queueManager, IEncode encodeService)
+ {
+ this.QueueManager = queueManager;
+ this.EncodeService = encodeService;
+
+ if (this.QueueManager == null)
+ {
+ throw new ArgumentNullException("queueManager");
+ }
+
+ if (this.QueueManager == null)
+ {
+ throw new ArgumentNullException("queueManager");
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="QueueProcessor"/> class.
+ /// This call also initializes the Encode and QueueManager services
+ /// </summary>
+ /// <param name="instanceId">
+ /// The instance id.
+ /// </param>
+ public QueueProcessor(int instanceId)
+ {
+ this.EncodeService = new Encode();
+ this.QueueManager = new QueueManager(instanceId);
+ }
+
+ #region Events
+
+ /// <summary>
+ /// Queue Progess Status
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The QueueProgressEventArgs.
+ /// </param>
+ public delegate void QueueProgressStatus(object sender, QueueProgressEventArgs e);
+
+ /// <summary>
+ /// Fires when the Queue has started
+ /// </summary>
+ public event QueueProgressStatus JobProcessingStarted;
+
+ /// <summary>
+ /// Fires when a pause to the encode queue has been requested.
+ /// </summary>
+ public event EventHandler QueuePaused;
+
+ /// <summary>
+ /// Fires when the entire encode queue has completed.
+ /// </summary>
+ public event EventHandler QueueCompleted;
+
+ /// <summary>
+ /// Invoke the JobProcessingStarted event
+ /// </summary>
+ /// <param name="e">
+ /// The QueueProgressEventArgs.
+ /// </param>
+ private void InvokeJobProcessingStarted(QueueProgressEventArgs e)
+ {
+ QueueProgressStatus handler = this.JobProcessingStarted;
+ if (handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+ /// <summary>
+ /// Invoke the QueuePaused event
+ /// </summary>
+ /// <param name="e">
+ /// The EventArgs.
+ /// </param>
+ private void InvokeQueuePaused(EventArgs e)
+ {
+ EventHandler handler = this.QueuePaused;
+ if (handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+ /// <summary>
+ /// Invoke the QueueCompleted event.
+ /// </summary>
+ /// <param name="e">
+ /// The EventArgs.
+ /// </param>
+ private void InvokeQueueCompleted(EventArgs e)
+ {
+ this.IsProcessing = false;
+
+ EventHandler handler = this.QueueCompleted;
+ if (handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets a value indicating whether IsProcessing.
+ /// </summary>
+ public bool IsProcessing { get; private set; }
+
+ /// <summary>
+ /// Gets the IEncodeService instance.
+ /// </summary>
+ public IEncode EncodeService { get; private set; }
+
+ /// <summary>
+ /// Gets the IQueueManager instance.
+ /// </summary>
+ public IQueueManager QueueManager { get; private set; }
+
+ #endregion
+
+ /// <summary>
+ /// Starts encoding the first job in the queue and continues encoding until all jobs
+ /// have been encoded.
+ /// </summary>
+ public void Start()
+ {
+ if (IsProcessing)
+ {
+ throw new Exception("Already Processing the Queue");
+ }
+
+ IsProcessing = true;
+ this.EncodeService.EncodeCompleted += this.EncodeServiceEncodeCompleted;
+ this.ProcessNextJob();
+ }
+
+ /// <summary>
+ /// Requests a pause of the encode queue.
+ /// </summary>
+ public void Pause()
+ {
+ this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted;
+ this.InvokeQueuePaused(EventArgs.Empty);
+ this.IsProcessing = false;
+ }
+
+ /// <summary>
+ /// After an encode is complete, move onto the next job.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The EncodeCompletedEventArgs.
+ /// </param>
+ private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e)
+ {
+ // Growl
+ if (Init.GrowlEncode)
+ GrowlCommunicator.Notify("Encode Completed",
+ "Put down that cocktail...\nyour Handbrake encode is done.");
+
+ if (!e.Successful)
+ {
+ this.Pause();
+ MessageBox.Show(e.Exception + e.ErrorInformation);
+ }
+
+ // Handling Log Data
+ this.EncodeService.ProcessLogs(this.QueueManager.LastProcessedJob.Destination);
+
+ // Move onto the next job.
+ this.ProcessNextJob();
+ }
+
+ /// <summary>
+ /// Run through all the jobs on the queue.
+ /// </summary>
+ private void ProcessNextJob()
+ {
+ if (this.EncodeService.IsEncoding || !this.IsProcessing)
+ {
+ // We don't want to try start a second encode, so just return out. The event will trigger the next encode automatically.
+ // Also, we don't want to start a new encode if we are paused.
+ return;
+ }
+
+ QueueTask job = this.QueueManager.GetNextJobForProcessing();
+ if (job != null)
+ {
+ this.EncodeService.Start(job, true);
+ this.InvokeJobProcessingStarted(new QueueProgressEventArgs(job));
+ }
+ else
+ {
+ // No more jobs to process, so unsubscribe the event
+ this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted;
+
+ // Fire the event to tell connected services.
+ this.InvokeQueueCompleted(EventArgs.Empty);
+
+ // Run the After encode completeion work
+ Finish();
+ }
+ }
+
+ /// <summary>
+ /// Perform an action after an encode. e.g a shutdown, standby, restart etc.
+ /// </summary>
+ private static void Finish()
+ {
+ // Growl
+ if (Init.GrowlQueue)
+ GrowlCommunicator.Notify("Queue Completed", "Put down that cocktail...\nyour Handbrake queue is done.");
+
+ // Do something whent he encode ends.
+ switch (Init.CompletionOption)
+ {
+ case "Shutdown":
+ Process.Start("Shutdown", "-s -t 60");
+ break;
+ case "Log off":
+ Win32.ExitWindowsEx(0, 0);
+ break;
+ case "Suspend":
+ Application.SetSuspendState(PowerState.Suspend, true, true);
+ break;
+ case "Hibernate":
+ Application.SetSuspendState(PowerState.Hibernate, true, true);
+ break;
+ case "Lock System":
+ Win32.LockWorkStation();
+ break;
+ case "Quit HandBrake":
+ Application.Exit();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Services/ScanService.cs b/win/CS/HandBrake.ApplicationServices/Services/ScanService.cs
new file mode 100644
index 000000000..7064d9358
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/ScanService.cs
@@ -0,0 +1,355 @@
+/* Scan.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Services
+{
+ using System;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Text;
+ using System.Threading;
+ using System.Windows.Forms;
+
+ using HandBrake.ApplicationServices.EventArgs;
+ using HandBrake.ApplicationServices.Parsing;
+ using HandBrake.ApplicationServices.Services.Interfaces;
+ using HandBrake.ApplicationServices.Utilities;
+
+ /// <summary>
+ /// Scan a Source
+ /// </summary>
+ public class ScanService : IScan
+ {
+ #region Private Variables
+
+ /// <summary>
+ /// A Lock object
+ /// </summary>
+ private static readonly object locker = new object();
+
+ /// <summary>
+ /// The CLI data parser
+ /// </summary>
+ private Parser readData;
+
+ /// <summary>
+ /// The Log Buffer
+ /// </summary>
+ private StringBuilder logBuffer;
+
+ /// <summary>
+ /// The line number thats been read to in the log file
+ /// </summary>
+ private int logFilePosition;
+
+ /// <summary>
+ /// The Process belonging to the CLI
+ /// </summary>
+ private Process hbProc;
+
+ #endregion
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ScanService"/> class.
+ /// </summary>
+ public ScanService()
+ {
+ }
+
+ #region Events
+
+ /// <summary>
+ /// Scan has Started
+ /// </summary>
+ public event EventHandler ScanStared;
+
+ /// <summary>
+ /// Scan has completed
+ /// </summary>
+ public event ScanCompletedStatus ScanCompleted;
+
+ /// <summary>
+ /// Encode process has progressed
+ /// </summary>
+ public event ScanProgessStatus ScanStatusChanged;
+
+ #endregion
+
+ #region Public Properties
+
+ /// <summary>
+ /// Gets a value indicating whether IsScanning.
+ /// </summary>
+ public bool IsScanning { get; private set; }
+
+ /// <summary>
+ /// Gets the Souce Data.
+ /// </summary>
+ public Source SouceData { get; private set; }
+
+ /// <summary>
+ /// Gets ActivityLog.
+ /// </summary>
+ public string ActivityLog
+ {
+ get
+ {
+ if (IsScanning)
+ return readData.Buffer.ToString();
+
+ if (logBuffer == null)
+ {
+ ResetLogReader(false);
+ ReadLastScanFile();
+ }
+
+ return logBuffer != null ? logBuffer.ToString() : string.Empty;
+ }
+ }
+
+ #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>
+ public void Scan(string sourcePath, int title)
+ {
+ Thread t = new Thread(unused => this.ScanSource(sourcePath, title));
+ t.Start();
+ }
+
+ /// <summary>
+ /// Kill the scan
+ /// </summary>
+ public void Stop()
+ {
+ try
+ {
+ // Try to clean things up as best as possible.
+ if (this.readData != null)
+ {
+ this.readData.OnScanProgress -= this.OnScanProgress;
+ }
+
+ if (hbProc != null && !hbProc.HasExited)
+ hbProc.Kill();
+ }
+ catch
+ {
+ // We don't really need to notify the user of any errors here.
+ }
+ }
+ #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>
+ private void ScanSource(object sourcePath, int title)
+ {
+ try
+ {
+ IsScanning = true;
+ if (this.ScanStared != null)
+ {
+ this.ScanStared(this, new EventArgs());
+ }
+
+ ResetLogReader(true);
+
+ string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");
+ string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
+ "\\HandBrake\\logs";
+ string dvdInfoPath = Path.Combine(
+ logDir,
+ string.Format("last_scan_log{0}.txt", Init.InstanceId == 0 ? string.Empty : Init.InstanceId.ToString()));
+
+ // Make we don't pick up a stale last_encode_log.txt (and that we have rights to the file)
+ if (File.Exists(dvdInfoPath))
+ {
+ File.Delete(dvdInfoPath);
+ }
+
+ string extraArguments = string.Empty;
+ if (Init.DisableDvdNav)
+ {
+ extraArguments = " --no-dvdnav";
+ }
+
+ if (title > 0)
+ {
+ extraArguments += " --scan ";
+ }
+
+ // Quick fix for "F:\\" style paths. Just get rid of the \\ so the CLI doesn't fall over.
+ // Sould probably clean up the escaping of the strings later.
+ string source = sourcePath.ToString().EndsWith("\\") ? sourcePath.ToString() : "\"" + sourcePath + "\"";
+
+ this.hbProc = new Process
+ {
+ StartInfo =
+ {
+ FileName = handbrakeCLIPath,
+ Arguments = String.Format(@" -i ""{0}"" -t{1} {2} -v ", sourcePath, title, extraArguments),
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ }
+ };
+
+ string command = String.Format(@" -i {0} -t{1} {2} -v ", source, title, extraArguments);
+
+ this.hbProc = new Process
+ {
+ StartInfo =
+ {
+ FileName = handbrakeCLIPath,
+ Arguments = command,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ }
+ };
+
+ // Start the Scan
+ this.hbProc.Start();
+
+ this.readData = new Parser(this.hbProc.StandardError.BaseStream);
+ this.readData.OnScanProgress += this.OnScanProgress;
+ this.SouceData = Source.Parse(this.readData);
+
+ // Write the Buffer out to file.
+ using (StreamWriter scanLog = new StreamWriter(dvdInfoPath))
+ {
+ // Only write the log file to disk if it's less than 100MB.
+ if (this.readData.Buffer.Length < 100000000)
+ {
+ scanLog.WriteLine(UtilityService.CreateCliLogHeader(null));
+ scanLog.Write(this.readData.Buffer);
+ logBuffer.AppendLine(this.readData.Buffer.ToString());
+ }
+ else
+ {
+ throw new Exception(
+ "The Log file has not been written to disk as it has grown above the 100MB limit. This indicates there was a problem during the scan process.");
+ }
+ }
+
+ IsScanning = false;
+
+ if (this.ScanCompleted != null)
+ {
+ this.ScanCompleted(this, new ScanCompletedEventArgs(true, null, string.Empty));
+ }
+ }
+ catch (Exception exc)
+ {
+ this.Stop();
+
+ if (this.ScanCompleted != null)
+ this.ScanCompleted(this, new ScanCompletedEventArgs(false, exc, "An Error has occured in ScanService.ScanSource()"));
+ }
+ }
+
+ /// <summary>
+ /// Read the log file
+ /// </summary>
+ private void ReadLastScanFile()
+ {
+ lock (locker)
+ {
+ // last_encode_log.txt is the primary log file. Since .NET can't read this file whilst the CLI is outputing to it (Not even in read only mode),
+ // we'll need to make a copy of it.
+ string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
+ "\\HandBrake\\logs";
+ string logFile = Path.Combine(logDir, string.Format("last_scan_log{0}.txt", Init.InstanceId == 0 ? string.Empty : Init.InstanceId.ToString()));
+ string logFile2 = Path.Combine(logDir, string.Format("tmp_appReadable_log{0}.txt", Init.InstanceId == 0 ? string.Empty : Init.InstanceId.ToString()));
+
+ try
+ {
+ // Make sure the application readable log file does not already exist. FileCopy fill fail if it does.
+ if (File.Exists(logFile2))
+ File.Delete(logFile2);
+
+ // Copy the log file.
+ if (File.Exists(logFile))
+ File.Copy(logFile, logFile2, true);
+ else
+ {
+ ResetLogReader(true);
+ return;
+ }
+
+ // Start the Reader
+ // Only use text which continues on from the last read line
+ StreamReader sr = new StreamReader(logFile2);
+ string line;
+ int i = 1;
+ while ((line = sr.ReadLine()) != null)
+ {
+ if (i > logFilePosition)
+ {
+ logBuffer.AppendLine(line);
+ logFilePosition++;
+ }
+ i++;
+ }
+ sr.Close();
+ sr.Dispose();
+ }
+ catch (Exception exc)
+ {
+ ResetLogReader(true);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Reset the Log Reader
+ /// </summary>
+ /// <param name="addHeader">
+ /// The add Header.
+ /// </param>
+ private void ResetLogReader(bool addHeader)
+ {
+ logFilePosition = 0;
+ logBuffer = new StringBuilder();
+ if (addHeader)
+ logBuffer.AppendLine(UtilityService.CreateCliLogHeader(null));
+ }
+
+ /// <summary>
+ /// Fire an event when the scan process progresses
+ /// </summary>
+ /// <param name="sender">the sender</param>
+ /// <param name="currentTitle">the current title being scanned</param>
+ /// <param name="titleCount">the total number of titles</param>
+ private void OnScanProgress(object sender, int currentTitle, int titleCount)
+ {
+ ScanProgressEventArgs eventArgs = new ScanProgressEventArgs
+ {
+ CurrentTitle = currentTitle,
+ Titles = titleCount
+ };
+
+ if (this.ScanStatusChanged != null)
+ {
+ this.ScanStatusChanged(this, eventArgs);
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Services/UpdateService.cs b/win/CS/HandBrake.ApplicationServices/Services/UpdateService.cs
new file mode 100644
index 000000000..5e65021e5
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Services/UpdateService.cs
@@ -0,0 +1,97 @@
+namespace HandBrake.ApplicationServices.Services
+{
+ using System;
+ using System.IO;
+ using System.Net;
+ using System.Threading;
+
+ using HandBrake.ApplicationServices.Model.General;
+ using HandBrake.ApplicationServices.Utilities;
+
+ /// <summary>
+ /// The Update Service
+ /// </summary>
+ public class UpdateService
+ {
+ /// <summary>
+ /// Begins checking for an update to HandBrake.
+ /// </summary>
+ /// <param name="callback">
+ /// The method that will be called when the check is finished.
+ /// </param>
+ /// <param name="debug">
+ /// Whether or not to execute this in debug mode.
+ /// </param>
+ /// <param name="url">
+ /// The url.
+ /// </param>
+ /// <param name="currentBuild">
+ /// The current Build.
+ /// </param>
+ /// <param name="skipBuild">
+ /// The skip Build.
+ /// </param>
+ /// <param name="currentVersion">
+ /// The current Version.
+ /// </param>
+ public static void BeginCheckForUpdates(AsyncCallback callback, bool debug, string url, int currentBuild, int skipBuild, string currentVersion)
+ {
+ ThreadPool.QueueUserWorkItem(delegate
+ {
+ try
+ {
+ // Initialize variables
+ WebRequest request = WebRequest.Create(url);
+ WebResponse response = request.GetResponse();
+ AppcastReader reader = new AppcastReader();
+
+ // Get the data, convert it to a string, and parse it into the AppcastReader
+ reader.GetUpdateInfo(new StreamReader(response.GetResponseStream()).ReadToEnd());
+
+ // Further parse the information
+ string build = reader.Build;
+
+ int latest = int.Parse(build);
+ int current = currentBuild;
+ int skip = skipBuild;
+
+ // If the user wanted to skip this version, don't report the update
+ if (latest == skip)
+ {
+ UpdateCheckInformation info = new UpdateCheckInformation { NewVersionAvailable = false };
+ callback(new UpdateCheckResult(debug, info));
+ return;
+ }
+
+ UpdateCheckInformation info2 = new UpdateCheckInformation
+ {
+ NewVersionAvailable = latest > current,
+ DescriptionUrl = reader.DescriptionUrl,
+ DownloadFile = reader.DownloadFile,
+ Build = reader.Build,
+ Version = reader.Version,
+ };
+ callback(new UpdateCheckResult(debug, info2));
+ }
+ catch (Exception exc)
+ {
+ callback(new UpdateCheckResult(debug, new UpdateCheckInformation { Error = exc }));
+ }
+ });
+ }
+
+ /// <summary>
+ /// End Check for Updates
+ /// </summary>
+ /// <param name="result">
+ /// The result.
+ /// </param>
+ /// <returns>
+ /// Update Check information
+ /// </returns>
+ public static UpdateCheckInformation EndCheckForUpdates(IAsyncResult result)
+ {
+ return ((UpdateCheckResult)result).Result;
+ }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/Settings.StyleCop b/win/CS/HandBrake.ApplicationServices/Settings.StyleCop
new file mode 100644
index 000000000..e61afbf69
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Settings.StyleCop
@@ -0,0 +1,14 @@
+<StyleCopSettings Version="4.3">
+ <Analyzers>
+ <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.DocumentationRules">
+ <Rules>
+ <Rule Name="ElementsMustBeDocumented">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">True</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ </Rules>
+ <AnalyzerSettings />
+ </Analyzer>
+ </Analyzers>
+</StyleCopSettings> \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Utilities/AppcastReader.cs b/win/CS/HandBrake.ApplicationServices/Utilities/AppcastReader.cs
new file mode 100644
index 000000000..8b0053a86
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Utilities/AppcastReader.cs
@@ -0,0 +1,119 @@
+/* AppcastReader.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Utilities
+{
+ using System;
+ using System.IO;
+ using System.Text.RegularExpressions;
+ using System.Xml;
+
+ /// <summary>
+ /// Appcast Reader - Used for parsing HandBrakes update file
+ /// </summary>
+ public class AppcastReader
+ {
+ /// <summary>
+ /// Gets Information about an update to HandBrake
+ /// </summary>
+ public Uri DescriptionUrl { get; private set; }
+
+ /// <summary>
+ /// Gets HandBrake's version from the appcast.xml file.
+ /// </summary>
+ public string Version { get; private set; }
+
+ /// <summary>
+ /// Gets HandBrake's Build from the appcast.xml file.
+ /// </summary>
+ public string Build { get; private set; }
+
+ /// <summary>
+ /// Gets the URL for update file.
+ /// </summary>
+ public string DownloadFile { get; private set; }
+
+ /// <summary>
+ /// Get the build information from the required appcasts. Run before accessing the public vars.
+ /// </summary>
+ /// <param name="input">
+ /// The input.
+ /// </param>
+ public void GetUpdateInfo(string input)
+ {
+ try
+ {
+ // Get the correct Appcast and set input.
+ XmlNode nodeItem = ReadRss(new XmlTextReader(new StringReader(input)));
+ string result = nodeItem.InnerXml;
+
+ // Regular Expressions
+ Match ver = Regex.Match(result, @"sparkle:version=""([0-9]*)\""");
+ Match verShort = Regex.Match(result, @"sparkle:shortVersionString=""(([svn]*)([0-9.\s]*))\""");
+
+ this.Build = ver.ToString().Replace("sparkle:version=", string.Empty).Replace("\"", string.Empty);
+ this.Version = verShort.ToString().Replace("sparkle:shortVersionString=", string.Empty).Replace(
+ "\"", string.Empty);
+ this.DownloadFile = nodeItem["windows"].InnerText;
+ this.DescriptionUrl = new Uri(nodeItem["sparkle:releaseNotesLink"].InnerText);
+ }
+ catch (Exception)
+ {
+ return;
+ }
+ }
+
+ /// <summary>
+ /// Read the RSS file.
+ /// </summary>
+ /// <param name="rssReader">
+ /// The RSS reader
+ /// </param>
+ /// <returns>
+ /// The read rss.
+ /// </returns>
+ private static XmlNode ReadRss(XmlReader rssReader)
+ {
+ XmlNode nodeItem = null;
+ XmlNode nodeChannel = null;
+ XmlNode nodeRss = null;
+
+ XmlDocument rssDoc = new XmlDocument();
+ rssDoc.Load(rssReader);
+
+ foreach (XmlNode t in rssDoc.ChildNodes)
+ {
+ if (t.Name == "rss")
+ {
+ nodeRss = t;
+ }
+ }
+
+ if (nodeRss != null)
+ {
+ foreach (XmlNode t in nodeRss.ChildNodes)
+ {
+ if (t.Name == "channel")
+ {
+ nodeChannel = t;
+ }
+ }
+ }
+
+ if (nodeChannel != null)
+ {
+ foreach (XmlNode t in nodeChannel.ChildNodes)
+ {
+ if (t.Name == "item")
+ {
+ nodeItem = t;
+ }
+ }
+ }
+
+ return nodeItem;
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs b/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs
new file mode 100644
index 000000000..ee1ab225a
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs
@@ -0,0 +1,664 @@
+/* PlistPresetHandler.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Utilities
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text;
+ using System.Windows.Forms;
+ using System.Xml;
+
+ using HandBrake.ApplicationServices.Functions;
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Model.Encoding;
+
+ /// <summary>
+ /// Plist Preset Converter
+ /// </summary>
+ public class PlistPresetHandler
+ {
+ /**
+ * TODO:
+ * - Update with the new vfr,pfr,cfr keys
+ * - Clean up this code, it's pretty nasty right now.
+ **/
+
+ #region Import
+
+ public static EncodeTask Import(string filename)
+ {
+ XmlNode root = loadFile(filename);
+ if (root == null) return null;
+
+ // We'll query a query parser object and use it's public var structures to store all the data.
+ // This will allow the preset loader logic to be used instead of writing custom logic just for this file.
+ EncodeTask parsed = new EncodeTask();
+ string qualityMode = string.Empty;
+
+ #region Get a List of Audio Track Objects
+ XmlNode audioListDict = root.ChildNodes[2].ChildNodes[0].FirstChild.ChildNodes[1];
+ List<AudioTrack> audioTracks = new List<AudioTrack>();
+
+ for (int i = 0; i < audioListDict.ChildNodes.Count; i++)
+ {
+ XmlNode audioChannel = audioListDict.ChildNodes[i];
+ AudioTrack track = new AudioTrack();
+
+ for (int subi = 0; subi < audioChannel.ChildNodes.Count; subi += 2)
+ {
+ // Audio Channel Information is here.
+ string key = audioChannel.ChildNodes[subi].InnerText;
+ string value = audioChannel.ChildNodes[subi + 1].InnerText;
+ switch (key)
+ {
+ case "AudioBitrate":
+ track.Bitrate = value;
+ break;
+ case "AudioEncoder":
+ track.Encoder = value.Replace("AAC (CoreAudio)", "AAC (faac)");
+ break;
+ case "AudioMixdown":
+ track.MixDown = value;
+ break;
+ case "AudioSamplerate":
+ track.SampleRate = value;
+ break;
+ case "AudioTrack":
+ track.Track = value;
+ break;
+ case "AudioTrackDRCSlider":
+ track.DRC = value;
+ break;
+ }
+ }
+ audioTracks.Add(track);
+ parsed.AudioTracks = audioTracks;
+ }
+ #endregion
+
+ #region Parse the reset of the plist keys into local variables
+
+ XmlNode presetSettings = root.ChildNodes[2].ChildNodes[0].FirstChild;
+
+ // Start from 2 to avoid the audio settings which we don't need.
+ for (int i = 2; i < presetSettings.ChildNodes.Count; i += 2)
+ {
+ string key = presetSettings.ChildNodes[i].InnerText;
+ string value = presetSettings.ChildNodes[i + 1].InnerText;
+
+ switch (key)
+ {
+ // Output Settings
+ case "FileFormat":
+ parsed.OutputFormat = Converters.GetFileFormat(value);
+ break;
+ case "Mp4HttpOptimize":
+ parsed.OptimizeMP4 = value == "1";
+ break;
+ case "Mp4LargeFile":
+ parsed.IPod5GSupport = value == "1";
+ break;
+ case "Mp4iPodCompatible":
+ parsed.IPod5GSupport = value == "1";
+ break;
+
+ // Picture Settings
+ case "PictureAutoCrop":
+ // Not used
+ break;
+ case "PictureTopCrop":
+ parsed.Cropping.Top = int.Parse(value);
+ break;
+ case "PictureBottomCrop":
+ parsed.Cropping.Bottom = int.Parse(value);
+ break;
+ case "PictureLeftCrop":
+ parsed.Cropping.Left = int.Parse(value);
+ break;
+ case "PictureRightCrop":
+ parsed.Cropping.Right = int.Parse(value);
+ break;
+ case "PictureHeight":
+ parsed.Height = int.Parse(value);
+ break;
+ case "PictureWidth":
+ parsed.Width = int.Parse(value);
+ break;
+ case "PictureKeepRatio":
+ parsed.KeepDisplayAspect = value == "1";
+ break;
+ case "PicturePAR":
+ switch (value)
+ {
+
+ case "0":
+ parsed.Anamorphic = Anamorphic.None;
+ break;
+ default:
+ parsed.Anamorphic = Anamorphic.Strict;
+ break;
+ case "2":
+ parsed.Anamorphic = Anamorphic.Loose;
+ break;
+ case "3":
+ parsed.Anamorphic = Anamorphic.Custom;
+ break;
+
+ }
+ break;
+
+ // Filters
+ case "PictureDeblock":
+ parsed.Deblock = int.Parse(value);
+ break;
+ case "PictureDecomb":
+ parsed.Decomb = Decomb.Off;
+ // Don't place custom here as it's handled in the filter panel
+ if (value == "2") parsed.Decomb = Decomb.Default;
+ break;
+ case "PictureDecombCustom":
+ if (value != string.Empty)
+ parsed.CustomDecomb = value;
+ break;
+ case "PictureDecombDeinterlace":
+ // Not Used
+ break;
+ case "PictureDeinterlace":
+ switch (value)
+ {
+ case "0":
+ parsed.Deinterlace = Deinterlace.Off;
+ break;
+ // Don't place custom here as it's handled in the filter panel
+ case "2":
+ parsed.Deinterlace = Deinterlace.Fast;
+ break;
+ case "3":
+ parsed.Deinterlace = Deinterlace.Slow;
+ break;
+ case "4":
+ parsed.Deinterlace = Deinterlace.Slower;
+ break;
+ }
+ break;
+ case "PictureDeinterlaceCustom":
+ if (value != string.Empty)
+ parsed.CustomDeinterlace = value;
+ break;
+ case "PictureDenoise":
+ switch (value)
+ {
+ case "0":
+ parsed.Denoise = Denoise.Off;
+ break;
+ // Don't place custom here as it's handled in the filter panel
+ case "2":
+ parsed.Denoise = Denoise.Weak;
+ break;
+ case "3":
+ parsed.Denoise = Denoise.Medium;
+ break;
+ case "4":
+ parsed.Denoise = Denoise.Strong;
+ break;
+ }
+
+ break;
+ case "PictureDenoiseCustom":
+ if (value != string.Empty)
+ parsed.CustomDenoise = value;
+ break;
+ case "PictureDetelecine":
+ parsed.Detelecine = Detelecine.Off;
+ if (value == "1") parsed.Detelecine = Detelecine.Default;
+ break;
+ case "PictureDetelecineCustom":
+ if (value != string.Empty)
+ parsed.CustomDetelecine = value;
+ break;
+
+ // Video Tab
+ case "VideoAvgBitrate":
+ parsed.VideoBitrate = int.Parse(value);
+ break;
+ case "VideoEncoder":
+ parsed.VideoEncoder = Converters.GetVideoEncoder(value);
+ break;
+ case "VideoFramerate":
+ parsed.Framerate = int.Parse(value);
+ break;
+ case "VideoGrayScale":
+ parsed.Grayscale = value == "1";
+ break;
+ case "VideoQualitySlider":
+ parsed.Quality = double.Parse(value);
+ break;
+ case "VideoQualityType": // The Type of Quality Mode used
+ qualityMode = value;
+ break;
+ case "VideoTurboTwoPass":
+ parsed.TurboFirstPass = value == "1";
+ break;
+ case "VideoTwoPass":
+ parsed.TwoPass = value == "1";
+ break;
+
+ // Chapter Markers Tab
+ case "ChapterMarkers":
+ parsed.IncludeChapterMarkers = value == "1";
+ break;
+
+ // Advanced x264 tab
+ case "x264Option":
+ parsed.AdvancedEncoderOptions = value;
+ break;
+
+ // Preset Information
+ case "PresetBuildNumber":
+ parsed.PresetBuildNumber = int.Parse(value);
+ break;
+ case "PresetDescription":
+ parsed.PresetDescription = value;
+ break;
+ case "PresetName":
+ parsed.PresetName = value;
+ break;
+ case "Type":
+ parsed.Type = value;
+ break;
+ case "UsesMaxPictureSettings":
+ parsed.UsesMaxPictureSettings = value == "1";
+ break;
+ case "UsesPictureFilters":
+ parsed.UsesPictureFilters = value == "1";
+ break;
+ case "UsesPictureSettings":
+ parsed.UsesPictureSettings = value == "1";
+ break;
+ }
+ }
+
+ // Kill any Quality values we don't need.
+ switch (qualityMode)
+ {
+ case "0": // FileSize
+ parsed.Quality = null;
+ parsed.VideoBitrate = null;
+ break;
+ case "1": // Avg Bitrate
+ parsed.Quality = null;
+ break;
+ case "2": // CQ
+ parsed.VideoBitrate = null;
+ break;
+ }
+ #endregion
+
+ return parsed;
+ }
+
+ private static XmlNode loadFile(string filename)
+ {
+ try
+ {
+ XmlNode root;
+
+ if (!File.Exists(filename))
+ return null;
+
+ StreamReader sr = File.OpenText(filename);
+ string fromfile = string.Empty;
+ int fileChar;
+ while ((fileChar = sr.Read()) != -1)
+ fromfile += Convert.ToChar(fileChar);
+
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(fromfile);
+
+ root = doc;
+ if (!root.HasChildNodes)
+ {
+ MessageBox.Show(
+ "The Preset file you selected appears to be invlaid or from an older version of HandBrake",
+ "Error",
+ MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return null;
+ }
+
+ return root;
+ }
+ catch (Exception)
+ {
+ MessageBox.Show(
+ "The Preset file you selected appears to be invlaid or from an older version of HandBrake.\n\n Please note, if you are exporting from the MacGui you may need to rebuild your preset so that it uses the current preset plist format.\n The MacGui does not currently update user presets automatically.",
+ "Error",
+ MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return null;
+ }
+ }
+ #endregion
+
+ #region Export
+
+ /// <summary>
+ /// Export a MacGui style plist preset.
+ /// </summary>
+ /// <param name="path">
+ /// The path.
+ /// </param>
+ /// <param name="preset">
+ /// The preset.
+ /// </param>
+ public static void Export(string path, Preset preset)
+ {
+ EncodeTask parsed = QueryParserUtility.Parse(preset.Query);
+ XmlTextWriter xmlWriter = new XmlTextWriter(path, Encoding.UTF8) { Formatting = Formatting.Indented };
+
+ // Header
+ xmlWriter.WriteStartDocument();
+ xmlWriter.WriteDocType("plist", "-//Apple//DTD PLIST 1.0//EN",
+ @"http://www.apple.com/DTDs/PropertyList-1.0.dtd", null);
+
+ xmlWriter.WriteStartElement("plist");
+ xmlWriter.WriteStartElement("array");
+
+ // Add New Preset Here. Can write multiple presets here if required in future.
+ WritePreset(xmlWriter, parsed, preset);
+
+ // Footer
+ xmlWriter.WriteEndElement();
+ xmlWriter.WriteEndElement();
+
+ xmlWriter.WriteEndDocument();
+
+ // Closeout
+ xmlWriter.Close();
+ }
+
+ /// <summary>
+ /// Write the Preset to a file
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="parsed">
+ /// The parsed.
+ /// </param>
+ /// <param name="preset">
+ /// The preset.
+ /// </param>
+ private static void WritePreset(XmlTextWriter xmlWriter, EncodeTask parsed, Preset preset)
+ {
+ xmlWriter.WriteStartElement("dict");
+ AudioListArrayDict(xmlWriter, parsed);
+ AddEncodeSettings(xmlWriter, parsed, preset);
+
+ xmlWriter.WriteEndElement();
+ }
+
+ /// <summary>
+ /// Add the encode settings to the preset
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="parsed">
+ /// The parsed.
+ /// </param>
+ /// <param name="preset">
+ /// The preset.
+ /// </param>
+ private static void AddEncodeSettings(XmlTextWriter xmlWriter, EncodeTask parsed, Preset preset)
+ {
+ AddEncodeElement(xmlWriter, "ChapterMarkers", "integer", parsed.IncludeChapterMarkers ? "1" : "0");
+ AddEncodeElement(xmlWriter, "Default", "integer", "0");
+ AddEncodeElement(xmlWriter, "FileFormat", "string", Converters.GetFileFormat(parsed.OutputFormat) + " file");
+ AddBooleanElement(xmlWriter, "Folder", false);
+ AddEncodeElement(xmlWriter, "Mp4HttpOptimize", "integer", parsed.OptimizeMP4 ? "1" : "0");
+ AddEncodeElement(xmlWriter, "Mp4LargeFile", "integer", parsed.LargeFile ? "1" : "0");
+ AddEncodeElement(xmlWriter, "Mp4iPodCompatible", "integer", parsed.IPod5GSupport ? "1" : "0");
+ AddEncodeElement(xmlWriter, "PictureAutoCrop", "integer", "1");
+ AddEncodeElement(xmlWriter, "PictureBottomCrop", "integer", parsed.Cropping.Bottom.ToString());
+
+ // Filters
+ AddEncodeElement(xmlWriter, "PictureDeblock", "integer", parsed.Deblock.ToString());
+
+ switch (parsed.Decomb)
+ {
+ case Decomb.Off:
+ AddEncodeElement(xmlWriter, "PictureDecomb", "integer", "0");
+ AddEncodeElement(xmlWriter, "PictureDecombCustom", "string", string.Empty);
+ break;
+ case Decomb.Default:
+ AddEncodeElement(xmlWriter, "PictureDecomb", "integer", "1");
+ AddEncodeElement(xmlWriter, "PictureDecombCustom", "string", string.Empty);
+ break;
+ default:
+ AddEncodeElement(xmlWriter, "PictureDecomb", "integer", "2");
+ AddEncodeElement(xmlWriter, "PictureDecombCustom", "string", parsed.CustomDecomb);
+ break;
+ }
+ AddEncodeElement(xmlWriter, "PictureDecombDeinterlace", "integer", parsed.Decomb != Decomb.Off ? "0" : "1");
+
+ switch (parsed.Deinterlace)
+ {
+ case Deinterlace.Off:
+ AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", "0");
+ AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", string.Empty);
+ break;
+ case Deinterlace.Fast:
+ AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", "1");
+ AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", string.Empty);
+ break;
+ case Deinterlace.Slow:
+ AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", "2");
+ AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", string.Empty);
+ break;
+ case Deinterlace.Slower:
+ AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", "3");
+ AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", string.Empty);
+ break;
+ default:
+ AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", "4");
+ AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", parsed.CustomDeinterlace);
+ break;
+ }
+
+ switch (parsed.Denoise)
+ {
+ case Denoise.Off:
+ AddEncodeElement(xmlWriter, "PictureDenoise", "integer", "0");
+ AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", string.Empty);
+ break;
+ case Denoise.Weak:
+ AddEncodeElement(xmlWriter, "PictureDenoise", "integer", "1");
+ AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", string.Empty);
+ break;
+ case Denoise.Medium:
+ AddEncodeElement(xmlWriter, "PictureDenoise", "integer", "2");
+ AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", string.Empty);
+ break;
+ case Denoise.Strong:
+ AddEncodeElement(xmlWriter, "PictureDenoise", "integer", "3");
+ AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", string.Empty);
+ break;
+ default:
+ AddEncodeElement(xmlWriter, "PictureDenoise", "integer", "4");
+ AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", parsed.CustomDenoise);
+ break;
+ }
+
+ int detelecine;
+ switch (parsed.Detelecine)
+ {
+ case Detelecine.Off:
+ detelecine = 0;
+ break;
+ case Detelecine.Default:
+ detelecine = 2;
+ break;
+ default:
+ detelecine = 1;
+ break;
+ }
+
+ AddEncodeElement(xmlWriter, "PictureDetelecine", "integer", detelecine.ToString());
+ AddEncodeElement(xmlWriter, "PictureDetelecineCustom", "string", detelecine == 1 ? parsed.CustomDecomb : string.Empty);
+
+ // Picture Settings
+ AddEncodeElement(xmlWriter, "PictureHeight", "integer", parsed.Height.ToString());
+ AddEncodeElement(xmlWriter, "PictureKeepRatio", "integer", parsed.KeepDisplayAspect ? "1" : "0");
+ AddEncodeElement(xmlWriter, "PictureLeftCrop", "integer", parsed.Cropping.Left.ToString());
+ AddEncodeElement(xmlWriter, "PictureModulus", "integer", parsed.Modulus.ToString());
+ AddEncodeElement(xmlWriter, "PicturePAR", "integer", ((int)parsed.Anamorphic).ToString());
+ AddEncodeElement(xmlWriter, "PictureRightCrop", "integer", parsed.Cropping.Right.ToString());
+ AddEncodeElement(xmlWriter, "PictureTopCrop", "integer", parsed.Cropping.Top.ToString());
+ AddEncodeElement(xmlWriter, "PictureWidth", "integer", parsed.Width.ToString());
+
+ // Preset Information
+ AddEncodeElement(xmlWriter, "PresetBuildNumber", "string", Init.Build.ToString());
+ AddEncodeElement(xmlWriter, "PresetDescription", "string", "No Description");
+ AddEncodeElement(xmlWriter, "PresetName", "string", preset.Name);
+ AddEncodeElement(xmlWriter, "Type", "integer", "1"); // 1 is user preset, 0 is built in
+
+ // Preset Settings
+ AddEncodeElement(xmlWriter, "UsesMaxPictureSettings", "integer", (parsed.MaxWidth != 0 || parsed.MaxHeight != 0) ? "1" : "0");
+ AddEncodeElement(xmlWriter, "UsesPictureFilters", "integer", "1");
+ AddEncodeElement(xmlWriter, "UsesPictureSettings", "integer", "2");
+
+ // Video Settings
+ AddEncodeElement(xmlWriter, "VideoAvgBitrate", "string", parsed.VideoBitrate.ToString());
+ AddEncodeElement(xmlWriter, "VideoEncoder", "string", Converters.GetGUIVideoEncoder(parsed.VideoEncoder));
+ AddEncodeElement(xmlWriter, "VideoFramerate", "string", parsed.Framerate.ToString());
+ AddEncodeElement(xmlWriter, "VideFrameratePFR", "integer", parsed.FramerateMode == FramerateMode.PFR ? "1" : "0");
+ AddEncodeElement(xmlWriter, "VideoGrayScale", "integer", parsed.Grayscale ? "1" : "0");
+ AddEncodeElement(xmlWriter, "VideoQualitySlider", "real", parsed.Quality.ToString());
+
+ int videoQualityType = 0;
+ if (parsed.VideoBitrate != null) videoQualityType = 1;
+ else if (parsed.Quality != null) videoQualityType = 2;
+
+ AddEncodeElement(xmlWriter, "VideoQualityType", "integer", videoQualityType.ToString());
+ AddEncodeElement(xmlWriter, "VideoTargetSize", "string", string.Empty);
+ AddEncodeElement(xmlWriter, "VideoTurboTwoPass", "integer", parsed.TurboFirstPass ? "1" : "0");
+ AddEncodeElement(xmlWriter, "VideoTwoPass", "integer", parsed.TwoPass ? "1" : "0");
+
+ // x264 string
+ AddEncodeElement(xmlWriter, "x264Option", "string", parsed.AdvancedEncoderOptions);
+ }
+
+ /// <summary>
+ /// Add a boolean element
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="keyName">
+ /// The key name.
+ /// </param>
+ /// <param name="value">
+ /// The value.
+ /// </param>
+ private static void AddBooleanElement(XmlTextWriter xmlWriter, string keyName, bool value)
+ {
+ xmlWriter.WriteStartElement("key");
+ xmlWriter.WriteString(keyName);
+ xmlWriter.WriteEndElement();
+ xmlWriter.WriteStartElement(value ? "true" : "false");
+ xmlWriter.WriteEndElement();
+ }
+
+ /// <summary>
+ /// Add an encode setting element
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="keyName">
+ /// The key name.
+ /// </param>
+ /// <param name="type">
+ /// The type.
+ /// </param>
+ /// <param name="value">
+ /// The value.
+ /// </param>
+ private static void AddEncodeElement(XmlTextWriter xmlWriter, string keyName, string type, string value)
+ {
+ xmlWriter.WriteElementString("key", keyName);
+
+ // This is a hack for Apples XML parser. It doesn't understand <integer /> so instead, always set a default value
+ // of 0 if the value is empty.
+ if (type == "integer" && string.IsNullOrEmpty(value))
+ {
+ value = "0";
+ }
+ xmlWriter.WriteElementString(type, value);
+ }
+
+ /// <summary>
+ /// Add an Audio Track Array Dict
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="parsed">
+ /// The parsed.
+ /// </param>
+ private static void AudioListArrayDict(XmlTextWriter xmlWriter, EncodeTask parsed)
+ {
+ xmlWriter.WriteStartElement("key");
+ xmlWriter.WriteString("AudioList");
+ xmlWriter.WriteEndElement();
+
+ xmlWriter.WriteStartElement("array");
+ foreach (AudioTrack track in parsed.AudioTracks)
+ {
+ AddAudioItem(xmlWriter, track);
+ }
+ xmlWriter.WriteEndElement();
+ }
+
+ /// <summary>
+ /// Add an audio track
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="audioTrack">
+ /// The audio track.
+ /// </param>
+ private static void AddAudioItem(XmlTextWriter xmlWriter, AudioTrack audioTrack)
+ {
+ xmlWriter.WriteStartElement("dict");
+
+ xmlWriter.WriteElementString("key", "AudioBitrate");
+ xmlWriter.WriteElementString("string", audioTrack.Bitrate);
+
+ xmlWriter.WriteElementString("key", "AudioEncoder");
+ xmlWriter.WriteElementString("string", audioTrack.Encoder);
+
+ xmlWriter.WriteElementString("key", "AudioMixdown");
+ xmlWriter.WriteElementString("string", audioTrack.MixDown);
+
+ xmlWriter.WriteElementString("key", "AudioSamplerate");
+ xmlWriter.WriteElementString("string", audioTrack.SampleRate);
+
+ xmlWriter.WriteElementString("key", "AudioTrack");
+ xmlWriter.WriteElementString("integer", audioTrack.Track);
+
+ xmlWriter.WriteElementString("key", "AudioTrackDRCSlider");
+ xmlWriter.WriteElementString("real", audioTrack.DRC);
+
+ xmlWriter.WriteElementString("key", "AudioTrackDescription");
+ xmlWriter.WriteElementString("string", "Unknown");
+
+ xmlWriter.WriteEndElement();
+ }
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Utilities/QueryParserUtility.cs b/win/CS/HandBrake.ApplicationServices/Utilities/QueryParserUtility.cs
new file mode 100644
index 000000000..ab90cf010
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Utilities/QueryParserUtility.cs
@@ -0,0 +1,415 @@
+/* QueryParser.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Utilities
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Text.RegularExpressions;
+
+ using HandBrake.ApplicationServices.Functions;
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Model.Encoding;
+
+ /// <summary>
+ /// Parse a CLI Query
+ /// </summary>
+ public class QueryParserUtility
+ {
+
+ /**
+ * TODO
+ * - Add support for PointToPointMode = Seconds or Frames
+ **/
+
+ /// <summary>
+ /// The Culture
+ /// </summary>
+ private static readonly CultureInfo Culture = new CultureInfo("en-US", false);
+
+ /// <summary>
+ /// Takes in a query which can be in any order and parses it.
+ /// All varibles are then set so they can be used elsewhere.
+ /// </summary>
+ /// <param name="input">A ClI Query</param>
+ /// <returns>A Parsed Query</returns>
+ public static EncodeTask Parse(string input)
+ {
+ var parsed = new EncodeTask();
+
+ #region Regular Expressions
+
+ // Source
+ Match title = Regex.Match(input, @"-t ([0-9]*)");
+ Match chapters = Regex.Match(input, @"-c ([0-9-]*)");
+
+ // Output Settings
+ Match format = Regex.Match(input, @"-f ([a-zA-Z0-9]*)");
+ Match grayscale = Regex.Match(input, @" -g");
+ Match largerMp4 = Regex.Match(input, @" -4");
+ Match ipodAtom = Regex.Match(input, @" -I");
+
+ // Picture Settings Tab
+ Match width = Regex.Match(input, @"-w ([0-9]*)");
+ Match height = Regex.Match(input, @"-l ([0-9]*)");
+ Match maxWidth = Regex.Match(input, @"-X ([0-9]*)");
+ Match maxHeight = Regex.Match(input, @"-Y ([0-9]*)");
+ Match crop = Regex.Match(input, @"--crop ([0-9]*):([0-9]*):([0-9]*):([0-9]*)");
+
+ Match looseAnamorphic = Regex.Match(input, @"--loose-anamorphic");
+ Match strictAnamorphic = Regex.Match(input, @"--strict-anamorphic");
+ Match customAnamorphic = Regex.Match(input, @"--custom-anamorphic");
+
+ Match keepDisplayAsect = Regex.Match(input, @"--keep-display-aspect");
+ Match displayWidth = Regex.Match(input, @"--display-width ([0-9]*)");
+ Match pixelAspect = Regex.Match(input, @"--pixel-aspect ([0-9]*):([0-9]*)");
+ Match modulus = Regex.Match(input, @"--modulus ([0-9]*)");
+
+ // Picture Settings - Filters
+ Match decomb = Regex.Match(input, @" --decomb");
+ Match decombValue = Regex.Match(input, @" --decomb=\""([a-zA-Z0-9.:]*)\""");
+ Match deinterlace = Regex.Match(input, @"--deinterlace=\""([a-zA-Z0-9.:]*)\""");
+ Match denoise = Regex.Match(input, @"--denoise=\""([a-zA-Z0-9.:]*)\""");
+ Match deblock = Regex.Match(input, @"--deblock=([0-9:]*)");
+ Match detelecine = Regex.Match(input, @"--detelecine");
+ Match detelecineValue = Regex.Match(input, @" --detelecine=\""([a-zA-Z0-9.:]*)\""");
+
+ // Video Settings Tab
+ Match videoEncoder = Regex.Match(input, @"-e ([a-zA-Z0-9]*)");
+ Match videoFramerate = Regex.Match(input, @"-r ([0-9.]*)");
+ Match videoBitrate = Regex.Match(input, @"-b ([0-9]*)");
+ Match videoQuality = Regex.Match(input, @"-q ([0-9.]*)");
+ Match twoPass = Regex.Match(input, @" -2");
+ Match turboFirstPass = Regex.Match(input, @" -T");
+ Match optimizeMP4 = Regex.Match(input, @" -O");
+ Match pfr = Regex.Match(input, @" --pfr");
+ Match vfr = Regex.Match(input, @" --vfr");
+ Match cfr = Regex.Match(input, @" --cfr");
+
+ // Audio Settings Tab
+ Match noAudio = Regex.Match(input, @"-a none");
+ Match audioTracks = Regex.Match(input, @"-a ([0-9,]*)");
+ Match audioTrackMixes = Regex.Match(input, @"-6 ([0-9a-zA-Z,]*)");
+ Match audioEncoders = Regex.Match(input, @"-E ([a-zA-Z0-9+,:]*)");
+ Match audioBitrates = Regex.Match(input, @"-B ([0-9a-zA-Z,]*)"); // Auto = a-z
+ Match audioSampleRates = Regex.Match(input, @"-R ([0-9a-zA-Z.,]*)"); // Auto = a-z
+ Match drcValues = Regex.Match(input, @"-D ([0-9.,]*)");
+
+ // Chapters Tab
+ Match chapterMarkers = Regex.Match(input, @" -m");
+ Match chapterMarkersFileMode = Regex.Match(input, @"--markers");
+
+ // Advanced Tab
+ Match advanced = Regex.Match(input, @"-x ([.,/a-zA-Z0-9=:-]*)");
+
+ #endregion
+
+ #region Set Varibles
+
+ try
+ {
+ #region Source Tab
+
+ if (title.Success)
+ {
+ parsed.Title = int.Parse(title.ToString().Replace("-t ", string.Empty));
+ }
+
+ if (chapters.Success)
+ {
+ parsed.PointToPointMode = PointToPointMode.Chapters;
+ string[] actTitles = chapters.ToString().Replace("-c ", string.Empty).Split('-');
+ parsed.StartPoint = int.Parse(actTitles[0]);
+ if (actTitles.Length > 1)
+ {
+ parsed.EndPoint = int.Parse(actTitles[1]);
+ }
+
+ if ((parsed.StartPoint == 1) && (parsed.EndPoint == 0))
+ {
+ parsed.EndPoint = parsed.StartPoint;
+ }
+ }
+
+ #endregion
+
+ #region Output Settings
+
+ if (format.Success)
+ {
+ parsed.OutputFormat = Converters.GetFileFormat(format.Groups[1].ToString());
+ }
+ parsed.LargeFile = largerMp4.Success;
+ parsed.IPod5GSupport = ipodAtom.Success;
+ parsed.OptimizeMP4 = optimizeMP4.Success;
+
+ #endregion
+
+ #region Picture Tab
+
+ if (width.Success)
+ parsed.Width = int.Parse(width.Groups[0].Value.Replace("-w ", string.Empty));
+
+ if (height.Success)
+ parsed.Height = int.Parse(height.Groups[0].Value.Replace("-l ", string.Empty));
+
+ if (maxWidth.Success)
+ parsed.MaxWidth = int.Parse(maxWidth.Groups[0].Value.Replace("-X ", string.Empty));
+
+ if (maxHeight.Success)
+ parsed.MaxHeight = int.Parse(maxHeight.Groups[0].Value.Replace("-Y ", string.Empty));
+
+ if (crop.Success)
+ {
+ try
+ {
+ string values = crop.ToString().Replace("--crop ", string.Empty);
+ string[] actCropValues = values.Split(':');
+ parsed.Cropping = new Cropping(
+ int.Parse(actCropValues[0]),
+ int.Parse(actCropValues[1]),
+ int.Parse(actCropValues[2]),
+ int.Parse(actCropValues[3]));
+ }
+ catch (Exception)
+ {
+ // No need to do anything.
+ }
+ }
+
+ if (strictAnamorphic.Success)
+ parsed.Anamorphic = Anamorphic.Strict;
+ else if (looseAnamorphic.Success)
+ parsed.Anamorphic = Anamorphic.Loose;
+ else if (customAnamorphic.Success)
+ parsed.Anamorphic = Anamorphic.Custom;
+ else
+ parsed.Anamorphic = Anamorphic.None;
+
+ parsed.KeepDisplayAspect = keepDisplayAsect.Success;
+
+ if (displayWidth.Success)
+ parsed.DisplayWidth =
+ double.Parse(displayWidth.Groups[0].Value.Replace("--display-width ", string.Empty));
+
+ if (pixelAspect.Success)
+ parsed.PixelAspectX = int.Parse(pixelAspect.Groups[1].Value.Replace("--pixel-aspect ", string.Empty));
+
+ if (pixelAspect.Success && pixelAspect.Groups.Count >= 3)
+ parsed.PixelAspectY = int.Parse(pixelAspect.Groups[2].Value.Replace("--pixel-aspect ", string.Empty));
+
+ if (modulus.Success)
+ parsed.Modulus = int.Parse(modulus.Groups[0].Value.Replace("--modulus ", string.Empty));
+
+ #endregion
+
+ #region Filters
+
+ parsed.Decomb = Decomb.Off;
+ if (decomb.Success)
+ {
+ parsed.Decomb = Decomb.Default;
+ if (decombValue.Success)
+ {
+ parsed.CustomDecomb = decombValue.ToString().Replace("--decomb=", string.Empty).Replace("\"", string.Empty);
+ }
+ }
+
+ parsed.Deinterlace = Deinterlace.Off;
+ if (deinterlace.Success)
+ {
+ switch (deinterlace.ToString().Replace("--deinterlace=", string.Empty).Replace("\"", string.Empty).ToLower())
+ {
+ case "fast":
+ parsed.Deinterlace = Deinterlace.Fast;
+ break;
+ case "slow":
+ parsed.Deinterlace = Deinterlace.Slow;
+ break;
+ case "slower":
+ parsed.Deinterlace = Deinterlace.Slower;
+ break;
+ case "slowest":
+ parsed.Deinterlace = Deinterlace.Slowest;
+ break;
+ default:
+ parsed.Deinterlace = Deinterlace.Custom;
+ parsed.CustomDeinterlace = deinterlace.ToString().Replace("--deinterlace=", string.Empty).Replace("\"", string.Empty).ToLower();
+ break;
+ }
+ }
+
+ parsed.Denoise = Denoise.Off;
+ if (denoise.Success)
+ {
+ switch (denoise.ToString().Replace("--denoise=", string.Empty).Replace("\"", string.Empty))
+ {
+ case "weak":
+ parsed.Denoise = Denoise.Weak;
+ break;
+ case "medium":
+ parsed.Denoise = Denoise.Medium;
+ break;
+ case "strong":
+ parsed.Denoise = Denoise.Strong;
+ break;
+ default:
+ parsed.Denoise = Denoise.Custom;
+ parsed.CustomDenoise = denoise.ToString().Replace("--denoise=", string.Empty).Replace("\"", string.Empty);
+ break;
+ }
+ }
+
+ parsed.Deblock = 0;
+ if (deblock.Success)
+ {
+ int dval;
+ int.TryParse(deblock.ToString().Replace("--deblock=", string.Empty), out dval);
+ parsed.Deblock = dval;
+ }
+
+ parsed.Detelecine = Detelecine.Off;
+ if (detelecine.Success)
+ {
+ parsed.Detelecine = Detelecine.Default;
+ if (detelecineValue.Success)
+ {
+ parsed.CustomDetelecine = detelecineValue.ToString().Replace("--detelecine=", string.Empty).Replace("\"", string.Empty);
+ parsed.Detelecine = Detelecine.Custom;
+ }
+ }
+
+ #endregion
+
+ #region Video Settings Tab
+
+ parsed.VideoEncoder = Converters.GetVideoEncoder(videoEncoder.ToString().Replace("-e ", string.Empty));
+
+ if (videoFramerate.Success)
+ {
+ double fps;
+ double.TryParse(videoFramerate.Groups[1].ToString(), out fps);
+ parsed.Framerate = fps;
+ }
+
+ if (pfr.Success)
+ parsed.FramerateMode = FramerateMode.PFR;
+ else if (cfr.Success)
+ parsed.FramerateMode = FramerateMode.CFR;
+ else
+ parsed.FramerateMode = FramerateMode.VFR; // Default to VFR
+
+ parsed.Grayscale = grayscale.Success;
+ parsed.TwoPass = twoPass.Success;
+ parsed.TurboFirstPass = turboFirstPass.Success;
+
+ if (videoBitrate.Success)
+ {
+ parsed.VideoEncodeRateType = VideoEncodeRateMode.AverageBitrate;
+ parsed.VideoBitrate = int.Parse(videoBitrate.ToString().Replace("-b ", string.Empty));
+ }
+
+ if (videoQuality.Success)
+ {
+ float quality = float.Parse(videoQuality.ToString().Replace("-q ", string.Empty), Culture);
+ parsed.Quality = quality;
+ }
+
+ #endregion
+
+ #region Audio Tab
+
+ // Find out how many tracks we need to add by checking how many encoders or audio tracks are selected.
+ int encoderCount = 0;
+ if (audioEncoders.Success)
+ {
+ string[] audioDataCounters = audioEncoders.ToString().Replace("-E ", string.Empty).Split(',');
+ encoderCount = audioDataCounters.Length;
+ }
+
+ // Get the data from the regular expression results
+ string[] trackData = null;
+ string[] trackMixes = null;
+ string[] trackEncoders = null;
+ string[] trackBitrates = null;
+ string[] trackSamplerates = null;
+ string[] trackDRCvalues = null;
+
+ if (audioTracks.Success)
+ trackData = audioTracks.ToString().Replace("-a ", string.Empty).Split(',');
+ if (audioTrackMixes.Success)
+ trackMixes = audioTrackMixes.ToString().Replace("-6 ", string.Empty).Split(',');
+ if (audioEncoders.Success)
+ trackEncoders = audioEncoders.ToString().Replace("-E ", string.Empty).Split(',');
+ if (audioBitrates.Success)
+ trackBitrates = audioBitrates.ToString().Replace("-B ", string.Empty).Split(',');
+ if (audioSampleRates.Success)
+ trackSamplerates = audioSampleRates.ToString().Replace("-R ", string.Empty).Split(',');
+ if (drcValues.Success)
+ trackDRCvalues = drcValues.ToString().Replace("-D ", string.Empty).Split(',');
+
+ // Create new Audio Track Classes and store them in the ArrayList
+ List<AudioTrack> allAudioTrackInfo = new List<AudioTrack>();
+ for (int x = 0; x < encoderCount; x++)
+ {
+ AudioTrack track = new AudioTrack();
+ if (trackData != null)
+ if (trackData.Length >= (x + 1)) // Audio Track
+ track.Track = trackData[x].Trim();
+
+ if (trackMixes != null)
+ if (trackMixes.Length >= (x + 1)) // Audio Mix
+ track.MixDown = Converters.GetMixDown(trackMixes[x].Trim());
+
+ if (trackEncoders != null)
+ if (trackEncoders.Length >= (x + 1)) // Audio Mix
+ track.Encoder = Converters.GetGUIAudioEncoder(trackEncoders[x].Trim());
+
+ if (trackBitrates != null)
+ if (trackBitrates.Length >= (x + 1)) // Audio Encoder
+ track.Bitrate = trackBitrates[x].Trim() == "auto" ? "Auto" : trackBitrates[x].Trim();
+
+ if (trackSamplerates != null)
+ if (trackSamplerates.Length >= (x + 1)) // Audio SampleRate
+ track.SampleRate = trackSamplerates[x].Trim() == "0" ? "Auto" : trackSamplerates[x].Trim();
+
+ if (trackDRCvalues != null)
+ if (trackDRCvalues.Length >= (x + 1)) // Audio DRC Values
+ track.DRC = trackDRCvalues[x].Trim();
+
+ allAudioTrackInfo.Add(track);
+ }
+
+ parsed.AudioTracks = allAudioTrackInfo;
+
+ #endregion
+
+ #region Chapters Tab
+
+ if (chapterMarkersFileMode.Success || chapterMarkers.Success)
+ parsed.IncludeChapterMarkers = true;
+
+ #endregion
+
+ #region Advanced and other
+
+ if (advanced.Success)
+ parsed.AdvancedEncoderOptions = advanced.ToString().Replace("-x ", string.Empty);
+
+ #endregion
+ }
+ catch (Exception exc)
+ {
+ throw new Exception("An error has occured in the QueryParser Utility.", exc);
+ }
+
+ #endregion
+
+ return parsed;
+ }
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrake.ApplicationServices/Utilities/UtilityService.cs b/win/CS/HandBrake.ApplicationServices/Utilities/UtilityService.cs
new file mode 100644
index 000000000..3cddf5e0b
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/Utilities/UtilityService.cs
@@ -0,0 +1,131 @@
+/* UtilityService.cs $
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr>.
+ It may be used under the terms of the GNU General Public License. */
+
+namespace HandBrake.ApplicationServices.Utilities
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Text;
+ using System.Windows.Forms;
+
+ using HandBrake.ApplicationServices.Functions;
+ using HandBrake.ApplicationServices.Model;
+
+ /// <summary>
+ /// A Set of Static Utilites
+ /// </summary>
+ public class UtilityService
+ {
+ /// <summary>
+ /// The Default Log Directory
+ /// </summary>
+ private static readonly string LogDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
+
+ /// <summary>
+ /// Clear all the log files older than 30 Days
+ /// </summary>
+ /// <param name="daysToKeep">
+ /// The Number of Days to Keep
+ /// </param>
+ public static void ClearLogFiles(int daysToKeep)
+ {
+ if (Directory.Exists(LogDir))
+ {
+ // Get all the log files
+ DirectoryInfo info = new DirectoryInfo(LogDir);
+ FileInfo[] logFiles = info.GetFiles("*.txt");
+
+ // Delete Them
+ foreach (FileInfo file in logFiles)
+ {
+ if (file.LastWriteTime < DateTime.Now.AddDays(-daysToKeep))
+ {
+ if (!file.Name.Contains("last_scan_log.txt") && !file.Name.Contains("last_encode_log.txt"))
+ {
+ File.Delete(file.FullName);
+ }
+ else if (file.Length > 104857600)
+ {
+ File.Delete(file.FullName);
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Get a list of available DVD drives which are ready and contain DVD content.
+ /// </summary>
+ /// <returns>A List of Drives with their details</returns>
+ public static List<DriveInformation> GetDrives()
+ {
+ List<DriveInformation> drives = new List<DriveInformation>();
+ DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
+ int id = 0;
+ foreach (DriveInfo curDrive in theCollectionOfDrives)
+ {
+ if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady)
+ {
+ if (Directory.Exists(curDrive.RootDirectory + "VIDEO_TS") || Directory.Exists(curDrive.RootDirectory + "BDMV"))
+ {
+ drives.Add(
+ new DriveInformation
+ {
+ Id = id,
+ VolumeLabel = curDrive.VolumeLabel,
+ RootDirectory = curDrive.RootDirectory.ToString()
+ });
+ id++;
+ }
+ }
+ }
+
+ return drives;
+ }
+
+ /// <summary>
+ /// Get the Process ID of HandBrakeCLI for the current instance.
+ /// </summary>
+ /// <returns>A list of processes</returns>
+ public static Process[] GetCliProcess()
+ {
+ return Process.GetProcessesByName("HandBrakeCLI");
+ }
+
+ /// <summary>
+ /// Add the CLI Query to the Log File.
+ /// </summary>
+ /// <param name="encJob">
+ /// The Encode Job Object
+ /// </param>
+ /// <returns>
+ /// The create cli log header.
+ /// </returns>
+ public static string CreateCliLogHeader(QueueTask encJob)
+ {
+ StringBuilder logHeader = new StringBuilder();
+
+ logHeader.AppendLine(String.Format("# {0}", Init.HandBrakeGuiVersionString));
+ logHeader.AppendLine(String.Format("# Running: {0}", Environment.OSVersion));
+ logHeader.AppendLine(String.Format("# CPU: {0}", SystemInfo.GetCpuCount));
+ logHeader.AppendLine(String.Format("# Ram: {0} MB", SystemInfo.TotalPhysicalMemory));
+ logHeader.AppendLine(String.Format("# Screen: {0}x{1}", SystemInfo.ScreenBounds.Bounds.Width, SystemInfo.ScreenBounds.Bounds.Height));
+ logHeader.AppendLine(String.Format("# Temp Dir: {0}", Path.GetTempPath()));
+ logHeader.AppendLine(String.Format("# Install Dir: {0}", Application.StartupPath));
+ logHeader.AppendLine(String.Format("# Data Dir: {0}\n", Application.UserAppDataPath));
+
+ if (encJob != null)
+ {
+ logHeader.AppendLine(String.Format("# CLI Query: {0}", encJob.Query));
+ logHeader.AppendLine(String.Format("# User Query: {0}", encJob.CustomQuery));
+ }
+ logHeader.AppendLine("-------------------------------------------");
+
+ return logHeader.ToString();
+ }
+ }
+}
diff --git a/win/CS/HandBrake.ApplicationServices/app.config b/win/CS/HandBrake.ApplicationServices/app.config
new file mode 100644
index 000000000..e092c6c7c
--- /dev/null
+++ b/win/CS/HandBrake.ApplicationServices/app.config
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<configuration>
+ <configSections>
+ <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <section name="HandBrake.ApplicationServices.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
+ </sectionGroup>
+ </configSections>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup></configuration>