summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsr55 <[email protected]>2010-06-04 18:36:11 +0000
committersr55 <[email protected]>2010-06-04 18:36:11 +0000
commit73177393028b107b844b69e540b9aa29310e57ac (patch)
tree713ead7ebc1cec2e68330574bb54679486000790
parent6141bbf563d067e4c2574f85871f1da4e1b664f2 (diff)
WinGui:
- HandBrakeInterop Project. This can be used to tie into libhb.dll with C#. Thanks to RandomEdgy for writing this. - Made a few minor changes to this source to make most of the libhb stuff internal to the library only. Added a 2008 project file. (This won't compile yet) git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3352 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r--win/C#/interop/DisplayStringAttribute.cs29
-rw-r--r--win/C#/interop/EncodeProgressEventArgs.cs16
-rw-r--r--win/C#/interop/HandBrakeInstance.cs1124
-rw-r--r--win/C#/interop/HandBrakeInterop.5.0.ReSharper.user24
-rw-r--r--win/C#/interop/HandBrakeInterop.csproj143
-rw-r--r--win/C#/interop/HandBrakeInterop.sln20
-rw-r--r--win/C#/interop/HandBrakeInterop.suobin0 -> 20480 bytes
-rw-r--r--win/C#/interop/HandBrakeInterop2008.sln20
-rw-r--r--win/C#/interop/HbLib.cs1285
-rw-r--r--win/C#/interop/InteropUtilities.cs120
-rw-r--r--win/C#/interop/Language.cs38
-rw-r--r--win/C#/interop/LanguageCodes.cs255
-rw-r--r--win/C#/interop/MessageLoggedEventArgs.cs12
-rw-r--r--win/C#/interop/Model/Cropping.cs15
-rw-r--r--win/C#/interop/Model/EncodeJob.cs69
-rw-r--r--win/C#/interop/Model/Encoding/Anamorphic.cs19
-rw-r--r--win/C#/interop/Model/Encoding/AudioEncoder.cs25
-rw-r--r--win/C#/interop/Model/Encoding/AudioEncoding.cs17
-rw-r--r--win/C#/interop/Model/Encoding/Decomb.cs14
-rw-r--r--win/C#/interop/Model/Encoding/Deinterlace.cs16
-rw-r--r--win/C#/interop/Model/Encoding/Denoise.cs16
-rw-r--r--win/C#/interop/Model/Encoding/Detelecine.cs14
-rw-r--r--win/C#/interop/Model/Encoding/EncodingProfile.cs111
-rw-r--r--win/C#/interop/Model/Encoding/Mixdown.cs25
-rw-r--r--win/C#/interop/Model/Encoding/OutputExtension.cs13
-rw-r--r--win/C#/interop/Model/Encoding/OutputFormat.cs16
-rw-r--r--win/C#/interop/Model/Encoding/VideoEncodeRateType.cs14
-rw-r--r--win/C#/interop/Model/Encoding/VideoEncoder.cs19
-rw-r--r--win/C#/interop/Model/Size.cs19
-rw-r--r--win/C#/interop/Model/SourceSubtitle.cs29
-rw-r--r--win/C#/interop/Model/SourceType.cs10
-rw-r--r--win/C#/interop/Model/SrtSubtitle.cs28
-rw-r--r--win/C#/interop/Model/Subtitles.cs13
-rw-r--r--win/C#/interop/NativeList.cs34
-rw-r--r--win/C#/interop/Properties/AssemblyInfo.cs36
-rw-r--r--win/C#/interop/ScanProgressEventArgs.cs13
-rw-r--r--win/C#/interop/SourceData/AudioTrack.cs80
-rw-r--r--win/C#/interop/SourceData/Chapter.cs38
-rw-r--r--win/C#/interop/SourceData/Subtitle.cs70
-rw-r--r--win/C#/interop/SourceData/SubtitleType.cs13
-rw-r--r--win/C#/interop/SourceData/Title.cs115
41 files changed, 3987 insertions, 0 deletions
diff --git a/win/C#/interop/DisplayStringAttribute.cs b/win/C#/interop/DisplayStringAttribute.cs
new file mode 100644
index 000000000..3f7e62d87
--- /dev/null
+++ b/win/C#/interop/DisplayStringAttribute.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ [AttributeUsage(AttributeTargets.Field)]
+ public sealed class DisplayStringAttribute : Attribute
+ {
+ private readonly string value;
+
+ public string Value
+ {
+ get { return value; }
+ }
+
+ public string ResourceKey { get; set; }
+
+ public DisplayStringAttribute(string v)
+ {
+ this.value = v;
+ }
+
+ public DisplayStringAttribute()
+ {
+ }
+ }
+}
diff --git a/win/C#/interop/EncodeProgressEventArgs.cs b/win/C#/interop/EncodeProgressEventArgs.cs
new file mode 100644
index 000000000..7f08595a7
--- /dev/null
+++ b/win/C#/interop/EncodeProgressEventArgs.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public class EncodeProgressEventArgs : EventArgs
+ {
+ public float FractionComplete { get; set; }
+ public float CurrentFrameRate { get; set; }
+ public float AverageFrameRate { get; set; }
+ public TimeSpan EstimatedTimeLeft { get; set; }
+ public int Pass { get; set; }
+ }
+}
diff --git a/win/C#/interop/HandBrakeInstance.cs b/win/C#/interop/HandBrakeInstance.cs
new file mode 100644
index 000000000..c9d1e1a45
--- /dev/null
+++ b/win/C#/interop/HandBrakeInstance.cs
@@ -0,0 +1,1124 @@
+namespace HandBrake.Interop
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using System.Runtime.InteropServices;
+ using System.Text;
+ using System.Timers;
+ using System.Threading;
+ using System.Windows.Media.Imaging;
+ using HandBrake.SourceData;
+ using HandBrake.Interop;
+
+ /// <summary>
+ /// A wrapper for a HandBrake instance.
+ /// </summary>
+ public class HandBrakeInstance : IDisposable
+ {
+ /// <summary>
+ /// The number of MS between status polls when scanning.
+ /// </summary>
+ private const double ScanPollIntervalMs = 200;
+
+ /// <summary>
+ /// The number of MS between status polls when encoding.
+ /// </summary>
+ private const double EncodePollIntervalMs = 200;
+
+ /// <summary>
+ /// X264 options to add for a turbo first pass.
+ /// </summary>
+ private const string TurboX264Opts = "ref=1:subme=2:me=dia:analyse=none:trellis=0:no-fast-pskip=0:8x8dct=0:weightb=0";
+
+ /// <summary>
+ /// The native handle to the HandBrake instance.
+ /// </summary>
+ private IntPtr hbHandle;
+
+ /// <summary>
+ /// The timer to poll for scan status.
+ /// </summary>
+ private System.Timers.Timer scanPollTimer;
+
+ /// <summary>
+ /// The timer to poll for encode status.
+ /// </summary>
+ private System.Timers.Timer encodePollTimer;
+
+ /// <summary>
+ /// The list of original titles in native structure form.
+ /// </summary>
+ private List<hb_title_s> originalTitles;
+
+ /// <summary>
+ /// The list of titles on this instance.
+ /// </summary>
+ private List<Title> titles;
+
+ /// <summary>
+ /// A list of native memory locations allocated by this instance.
+ /// </summary>
+ private List<IntPtr> encodeAllocatedMemory;
+
+ /// <summary>
+ /// The callback for log messages from HandBrake.
+ /// </summary>
+ private static LoggingCallback loggingCallback;
+
+ /// <summary>
+ /// The callback for error messages from HandBrake.
+ /// </summary>
+ private static LoggingCallback errorCallback;
+
+ /// <summary>
+ /// Fires for progress updates when scanning.
+ /// </summary>
+ public event EventHandler<ScanProgressEventArgs> ScanProgress;
+
+ /// <summary>
+ /// Fires when a scan has completed.
+ /// </summary>
+ public event EventHandler<EventArgs> ScanCompleted;
+
+ /// <summary>
+ /// Fires for progress updates when encoding.
+ /// </summary>
+ public event EventHandler<EncodeProgressEventArgs> EncodeProgress;
+
+ /// <summary>
+ /// Fires when an encode has completed.
+ /// </summary>
+ public event EventHandler<EventArgs> EncodeCompleted;
+
+ /// <summary>
+ /// Fires when HandBrake has logged a message.
+ /// </summary>
+ public static event EventHandler<MessageLoggedEventArgs> MessageLogged;
+
+ /// <summary>
+ /// Fires when HandBrake has logged an error.
+ /// </summary>
+ public static event EventHandler<MessageLoggedEventArgs> ErrorLogged;
+
+ /// <summary>
+ /// Destructor.
+ /// </summary>
+ ~HandBrakeInstance()
+ {
+ this.Dispose(false);
+ }
+
+ /// <summary>
+ /// The list of titles on this instance.
+ /// </summary>
+ public List<Title> Titles
+ {
+ get
+ {
+ return this.titles;
+ }
+ }
+
+ /// <summary>
+ /// Initializes this instance.
+ /// </summary>
+ /// <param name="verbosity"></param>
+ public void Initialize(int verbosity)
+ {
+ // Register the logger if we have not already
+ if (loggingCallback == null)
+ {
+ // Keep the callback as a member to prevent it from being garbage collected.
+ loggingCallback = new LoggingCallback(HandBrakeInstance.LoggingHandler);
+ errorCallback = new LoggingCallback(HandBrakeInstance.ErrorHandler);
+ HbLib.hb_register_logger(loggingCallback);
+ HbLib.hb_register_error_handler(errorCallback);
+ }
+
+ this.hbHandle = HbLib.hb_init(verbosity, update_check: 0);
+ }
+
+ /// <summary>
+ /// Handles log messages from HandBrake.
+ /// </summary>
+ /// <param name="message">The log message (including newline).</param>
+ public static void LoggingHandler(string message)
+ {
+ if (!string.IsNullOrEmpty(message))
+ {
+ string[] messageParts = message.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
+
+ if (messageParts.Length > 0)
+ {
+ if (MessageLogged != null)
+ {
+ MessageLogged(null, new MessageLoggedEventArgs { Message = messageParts[0] });
+ }
+
+ System.Diagnostics.Debug.WriteLine(messageParts[0]);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Handles errors from HandBrake.
+ /// </summary>
+ /// <param name="message">The error message.</param>
+ public static void ErrorHandler(string message)
+ {
+ if (!string.IsNullOrEmpty(message))
+ {
+ if (ErrorLogged != null)
+ {
+ ErrorLogged(null, new MessageLoggedEventArgs { Message = message });
+ }
+
+ System.Diagnostics.Debug.WriteLine("ERROR: " + message);
+ }
+ }
+
+ /// <summary>
+ /// Starts scanning the given path.
+ /// </summary>
+ /// <param name="path">The path to the video to scan.</param>
+ /// <param name="previewCount">The number of preview images to make.</param>
+ public void StartScan(string path, int previewCount)
+ {
+ this.StartScan(path, previewCount, 0);
+ }
+
+ /// <summary>
+ /// Starts a scan of the given path.
+ /// </summary>
+ /// <param name="path">The path of the video to scan.</param>
+ /// <param name="previewCount">The number of previews to make on each title.</param>
+ /// <param name="titleIndex">The title index to scan (1-based, 0 for all titles).</param>
+ public void StartScan(string path, int previewCount, int titleIndex)
+ {
+ HbLib.hb_scan(hbHandle, path, titleIndex, previewCount, 1);
+ this.scanPollTimer = new System.Timers.Timer();
+ this.scanPollTimer.Interval = ScanPollIntervalMs;
+
+ // Lambda notation used to make sure we can view any JIT exceptions the method throws
+ this.scanPollTimer.Elapsed += (o, e) =>
+ {
+ this.PollScanProgress();
+ };
+ this.scanPollTimer.Start();
+ }
+
+ /// <summary>
+ /// Gets an image for the given job and preview
+ /// </summary>
+ /// <remarks>
+ /// Only incorporates sizing and aspect ratio into preview image.
+ /// </remarks>
+ /// <param name="job">The encode job to preview.</param>
+ /// <param name="previewNumber">The index of the preview to get (0-based).</param>
+ /// <returns>An image with the requested preview.</returns>
+ public BitmapImage GetPreview(EncodeJob job, int previewNumber)
+ {
+ hb_title_s title = this.GetOriginalTitle(job.Title);
+
+ hb_job_s nativeJob = InteropUtilities.ReadStructure<hb_job_s>(title.job);
+ List<IntPtr> allocatedMemory = this.ApplyJob(ref nativeJob, job, false, 0, 0);
+
+ // Create a new job pointer from our modified job object
+ IntPtr newJob = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_job_s)));
+ Marshal.StructureToPtr(nativeJob, newJob, false);
+ allocatedMemory.Add(newJob);
+
+ int outputWidth = nativeJob.width;
+ int outputHeight = nativeJob.height;
+ int imageBufferSize = outputWidth * outputHeight * 4;
+ IntPtr nativeBuffer = Marshal.AllocHGlobal(imageBufferSize);
+ allocatedMemory.Add(nativeBuffer);
+ HbLib.hb_set_job(this.hbHandle, job.Title, ref nativeJob);
+ HbLib.hb_get_preview_by_index(this.hbHandle, job.Title, previewNumber, nativeBuffer);
+
+ // Copy the filled image buffer to a managed array.
+ byte[] managedBuffer = new byte[imageBufferSize];
+ Marshal.Copy(nativeBuffer, managedBuffer, 0, imageBufferSize);
+
+ InteropUtilities.FreeMemory(allocatedMemory);
+
+ System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outputWidth, outputHeight);
+ System.Drawing.Imaging.BitmapData bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, outputWidth, outputHeight), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
+
+ IntPtr ptr = bitmapData.Scan0;
+
+ for (int i = 0; i < nativeJob.height; i++)
+ {
+ Marshal.Copy(managedBuffer, i * nativeJob.width * 4, ptr, nativeJob.width * 4);
+ ptr = IntPtr.Add(ptr, bitmapData.Stride);
+ }
+
+ bitmap.UnlockBits(bitmapData);
+ //bitmap.Save(@"d:\docs\test_" + previewNumber + ".png", System.Drawing.Imaging.ImageFormat.Png);
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Bmp);
+ bitmap.Dispose();
+
+ BitmapImage wpfBitmap = new BitmapImage();
+ wpfBitmap.BeginInit();
+ wpfBitmap.CacheOption = BitmapCacheOption.OnLoad;
+ wpfBitmap.StreamSource = memoryStream;
+ wpfBitmap.EndInit();
+
+ return wpfBitmap;
+ }
+ }
+
+ /// <summary>
+ /// Starts an encode with the given job.
+ /// </summary>
+ /// <param name="job">The job to start.</param>
+ public void StartEncode(EncodeJob job)
+ {
+ this.StartEncode(job, false, 0, 0);
+ }
+
+ /// <summary>
+ /// Starts an encode with the given job.
+ /// </summary>
+ /// <param name="job">The job to start.</param>
+ /// <param name="preview">True if this is a preview encode.</param>
+ /// <param name="previewNumber">The preview number to start the encode at (0-based).</param>
+ /// <param name="previewSeconds">The number of seconds in the preview.</param>
+ public void StartEncode(EncodeJob job, bool preview, int previewNumber, int previewSeconds)
+ {
+ hb_job_s nativeJob = InteropUtilities.ReadStructure<hb_job_s>(this.GetOriginalTitle(job.Title).job);
+ this.encodeAllocatedMemory = this.ApplyJob(ref nativeJob, job, preview, previewNumber, previewSeconds);
+
+ if (!preview && job.EncodingProfile.IncludeChapterMarkers)
+ {
+ Title title = this.GetTitle(job.Title);
+ int numChapters = title.Chapters.Count;
+
+ if (job.UseDefaultChapterNames)
+ {
+ for (int i = 0; i < numChapters; i++)
+ {
+ HbLib.hb_set_chapter_name(this.hbHandle, job.Title, i + 1, "Chapter " + (i + 1));
+ }
+ }
+ else
+ {
+ for (int i = 0; i < numChapters; i++)
+ {
+ HbLib.hb_set_chapter_name(this.hbHandle, job.Title, i + 1, job.CustomChapterNames[i]);
+ }
+ }
+ }
+
+ HbLib.hb_add(this.hbHandle, ref nativeJob);
+
+ if (job.EncodingProfile.TwoPass)
+ {
+ nativeJob.pass = 2;
+
+ string x264Opts = job.EncodingProfile.X264Options ?? string.Empty;
+ nativeJob.x264opts = Marshal.StringToHGlobalAnsi(x264Opts);
+ this.encodeAllocatedMemory.Add(nativeJob.x264opts);
+
+ HbLib.hb_add(this.hbHandle, ref nativeJob);
+ }
+
+ HbLib.hb_start(this.hbHandle);
+
+ this.encodePollTimer = new System.Timers.Timer();
+ this.encodePollTimer.Interval = EncodePollIntervalMs;
+
+ this.encodePollTimer.Elapsed += (o, e) =>
+ {
+ this.PollEncodeProgress();
+ };
+ this.encodePollTimer.Start();
+ }
+
+ /// <summary>
+ /// Pauses the current encode.
+ /// </summary>
+ public void PauseEncode()
+ {
+ HbLib.hb_pause(this.hbHandle);
+ }
+
+ /// <summary>
+ /// Resumes a paused encode.
+ /// </summary>
+ public void ResumeEncode()
+ {
+ HbLib.hb_resume(this.hbHandle);
+ }
+
+ /// <summary>
+ /// Stops the current encode.
+ /// </summary>
+ public void StopEncode()
+ {
+ HbLib.hb_stop(this.hbHandle);
+
+ // Also remove all jobs from the queue (in case we stopped a 2-pass encode)
+ var currentJobs = new List<IntPtr>();
+
+ int jobs = HbLib.hb_count(this.hbHandle);
+ for (int i = 0; i < jobs; i++)
+ {
+ currentJobs.Add(HbLib.hb_job(this.hbHandle, 0));
+ }
+
+ foreach (IntPtr job in currentJobs)
+ {
+ HbLib.hb_rem(this.hbHandle, job);
+ }
+ }
+
+ /// <summary>
+ /// Gets the final size when using Anamorphic for a given encode job.
+ /// </summary>
+ /// <param name="job">The encode job to use.</param>
+ /// <param name="width">The storage width.</param>
+ /// <param name="height">The storage height.</param>
+ /// <param name="parWidth">The pixel aspect X number.</param>
+ /// <param name="parHeight">The pixel aspect Y number.</param>
+ public void GetAnamorphicSize(EncodeJob job, out int width, out int height, out int parWidth, out int parHeight)
+ {
+ hb_job_s nativeJob = InteropUtilities.ReadStructure<hb_job_s>(this.GetOriginalTitle(job.Title).job);
+ List<IntPtr> allocatedMemory = this.ApplyJob(ref nativeJob, job, false, 0, 0);
+
+ int refWidth = 0;
+ int refHeight = 0;
+ int refParWidth = 0;
+ int refParHeight = 0;
+ HbLib.hb_set_job(this.hbHandle, job.Title, ref nativeJob);
+ HbLib.hb_set_anamorphic_size_by_index(this.hbHandle, job.Title, ref refWidth, ref refHeight, ref refParWidth, ref refParHeight);
+ //HbLib.hb_set_anamorphic_size(ref nativeJob, ref refWidth, ref refHeight, ref refParWidth, ref refParHeight);
+ InteropUtilities.FreeMemory(allocatedMemory);
+
+ width = refWidth;
+ height = refHeight;
+ parWidth = refParWidth;
+ parHeight = refParHeight;
+ }
+
+ /// <summary>
+ /// Frees any resources associated with this object.
+ /// </summary>
+ public void Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Call before app shutdown. Performs global cleanup.
+ /// </summary>
+ public static void DisposeGlobal()
+ {
+ HbLib.hb_global_close();
+ }
+
+ /// <summary>
+ /// Frees any resources associated with this object.
+ /// </summary>
+ /// <param name="disposing">True if managed objects as well as unmanaged should be disposed.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // Free other state (managed objects).
+ }
+
+ // Free unmanaged objects.
+ IntPtr handlePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
+ Marshal.WriteIntPtr(handlePtr, this.hbHandle);
+ HbLib.hb_close(handlePtr);
+ Marshal.FreeHGlobal(handlePtr);
+ }
+
+ /// <summary>
+ /// Checks the status of the ongoing scan.
+ /// </summary>
+ private void PollScanProgress()
+ {
+ hb_state_s state = new hb_state_s();
+ HbLib.hb_get_state(this.hbHandle, ref state);
+
+ if (state.state == NativeConstants.HB_STATE_SCANNING)
+ {
+ if (this.ScanProgress != null)
+ {
+ int currentTitle = state.param.scanning.title_cur;
+ int totalTitles = state.param.scanning.title_count;
+ this.ScanProgress(this, new ScanProgressEventArgs { CurrentTitle = currentTitle, Titles = totalTitles });
+ }
+ }
+ else if (state.state == NativeConstants.HB_STATE_SCANDONE)
+ {
+ this.titles = new List<Title>();
+
+ IntPtr listPtr = HbLib.hb_get_titles(this.hbHandle);
+ this.originalTitles = InteropUtilities.ConvertList<hb_title_s>(listPtr);
+
+ foreach (hb_title_s title in this.originalTitles)
+ {
+ var newTitle = this.ConvertTitle(title);
+ this.titles.Add(newTitle);
+ }
+
+ this.scanPollTimer.Stop();
+
+ if (this.ScanCompleted != null)
+ {
+ this.ScanCompleted(this, new EventArgs());
+ }
+ }
+ }
+
+ /// <summary>
+ /// Checks the status of the ongoing encode.
+ /// </summary>
+ private void PollEncodeProgress()
+ {
+ hb_state_s state = new hb_state_s();
+ HbLib.hb_get_state(this.hbHandle, ref state);
+
+ if (state.state == NativeConstants.HB_STATE_WORKING)
+ {
+ if (this.EncodeProgress != null)
+ {
+ var progressEventArgs = new EncodeProgressEventArgs
+ {
+ FractionComplete = state.param.working.progress,
+ CurrentFrameRate = state.param.working.rate_cur,
+ AverageFrameRate = state.param.working.rate_avg,
+ EstimatedTimeLeft = new TimeSpan(state.param.working.hours, state.param.working.minutes, state.param.working.seconds),
+ Pass = state.param.working.job_cur
+ };
+
+ this.EncodeProgress(this, progressEventArgs);
+ }
+ }
+ else if (state.state == NativeConstants.HB_STATE_MUXING)
+ {
+ //System.Diagnostics.Debug.WriteLine("Muxing...");
+ }
+ else if (state.state == NativeConstants.HB_STATE_WORKDONE)
+ {
+ InteropUtilities.FreeMemory(this.encodeAllocatedMemory);
+ this.encodePollTimer.Stop();
+
+ if (this.EncodeCompleted != null)
+ {
+ this.EncodeCompleted(this, new EventArgs());
+ }
+ }
+ }
+
+ /// <summary>
+ /// Applies the encoding job to the native memory structure and returns a list of memory
+ /// locations allocated during this.
+ /// </summary>
+ /// <param name="nativeJob">The native structure to apply to job info to.</param>
+ /// <param name="job">The job info to apply.</param>
+ /// <param name="preview">True if this is a preview encode.</param>
+ /// <param name="previewNumber">The preview number (0-based) to encode.</param>
+ /// <param name="previewSeconds">The number of seconds in the preview.</param>
+ /// <returns>The list of memory locations allocated for the job.</returns>
+ private List<IntPtr> ApplyJob(ref hb_job_s nativeJob, EncodeJob job, bool preview, int previewNumber, int previewSeconds)
+ {
+ var allocatedMemory = new List<IntPtr>();
+ Title title = this.GetTitle(job.Title);
+ hb_title_s originalTitle = this.GetOriginalTitle(job.Title);
+
+ EncodingProfile profile = job.EncodingProfile;
+
+ if (preview)
+ {
+ nativeJob.start_at_preview = previewNumber + 1;
+ nativeJob.seek_points = 10;
+
+ // There are 90,000 PTS per second.
+ nativeJob.pts_to_stop = previewSeconds * 90000;
+ }
+ else if (job.ChapterStart > 0 && job.ChapterEnd > 0)
+ {
+ nativeJob.chapter_start = job.ChapterStart;
+ nativeJob.chapter_end = job.ChapterEnd;
+ }
+ else
+ {
+ nativeJob.chapter_start = 1;
+ nativeJob.chapter_end = title.Chapters.Count;
+ }
+
+ nativeJob.chapter_markers = profile.IncludeChapterMarkers ? 1 : 0;
+
+ Cropping crop;
+
+ if (profile.CustomCropping)
+ {
+ crop = profile.Cropping;
+ }
+ else
+ {
+ crop = title.AutoCropDimensions;
+ }
+
+ nativeJob.crop[0] = crop.Top;
+ nativeJob.crop[1] = crop.Bottom;
+ nativeJob.crop[2] = crop.Left;
+ nativeJob.crop[3] = crop.Right;
+
+ List<IntPtr> filterList = new List<IntPtr>();
+ if (profile.Deinterlace != Deinterlace.Off)
+ {
+ nativeJob.deinterlace = 1;
+ string settings = null;
+
+ switch (profile.Deinterlace)
+ {
+ case Deinterlace.Fast:
+ settings = "-1";
+ break;
+ case Deinterlace.Slow:
+ settings = "2";
+ break;
+ case Deinterlace.Slower:
+ settings = "0";
+ break;
+ case Deinterlace.Custom:
+ settings = profile.CustomDeinterlace;
+ break;
+ default:
+ break;
+ }
+
+ this.AddFilter(filterList, NativeConstants.HB_FILTER_DEINTERLACE, settings, allocatedMemory);
+ //filterList.Add(HbLib.hb_get_filter_object(NativeConstants.HB_FILTER_DEINTERLACE, settings));
+ }
+ else
+ {
+ nativeJob.deinterlace = 0;
+ }
+
+ if (profile.Detelecine != Detelecine.Off)
+ {
+ string settings = null;
+ if (profile.Detelecine == Detelecine.Custom)
+ {
+ settings = profile.CustomDetelecine;
+ }
+
+ this.AddFilter(filterList, NativeConstants.HB_FILTER_DETELECINE, settings, allocatedMemory);
+ //filterList.Add(HbLib.hb_get_filter_object(NativeConstants.HB_FILTER_DETELECINE, settings));
+ }
+
+ if (profile.Decomb != Decomb.Off)
+ {
+ string settings = null;
+ if (profile.Decomb == Decomb.Custom)
+ {
+ settings = profile.CustomDecomb;
+ }
+
+ this.AddFilter(filterList, NativeConstants.HB_FILTER_DECOMB, settings, allocatedMemory);
+ //filterList.Add(HbLib.hb_get_filter_object(NativeConstants.HB_FILTER_DECOMB, settings));
+ }
+
+ if (profile.Deblock > 0)
+ {
+ this.AddFilter(filterList, NativeConstants.HB_FILTER_DEBLOCK, profile.Deblock.ToString(), allocatedMemory);
+ //filterList.Add(HbLib.hb_get_filter_object(NativeConstants.HB_FILTER_DEBLOCK, profile.Deblock.ToString()));
+ }
+
+ if (profile.Denoise != Denoise.Off)
+ {
+ string settings = null;
+ switch (profile.Denoise)
+ {
+ case Denoise.Weak:
+ settings = "2:1:2:3";
+ break;
+ case Denoise.Medium:
+ settings = "3:2:2:3";
+ break;
+ case Denoise.Strong:
+ settings = "7:7:5:5";
+ break;
+ case Denoise.Custom:
+ settings = profile.CustomDenoise;
+ break;
+ default:
+ break;
+ }
+
+ this.AddFilter(filterList, NativeConstants.HB_FILTER_DENOISE, settings, allocatedMemory);
+ //filterList.Add(HbLib.hb_get_filter_object(NativeConstants.HB_FILTER_DENOISE, settings));
+ }
+
+ NativeList filterListNative = InteropUtilities.CreateIntPtrList(filterList);
+ nativeJob.filters = filterListNative.ListPtr;
+ allocatedMemory.AddRange(filterListNative.AllocatedMemory);
+
+ int width = profile.Width;
+ int height = profile.Height;
+
+ if (width == 0)
+ {
+ width = title.Resolution.Width;
+ }
+
+ if (profile.MaxWidth > 0 && width > profile.MaxWidth)
+ {
+ width = profile.MaxWidth;
+ }
+
+ if (height == 0)
+ {
+ height = title.Resolution.Height;
+ }
+
+ if (profile.MaxHeight > 0 && height > profile.MaxHeight)
+ {
+ height = profile.MaxHeight;
+ }
+
+ nativeJob.grayscale = profile.Grayscale ? 1 : 0;
+
+ switch (profile.Anamorphic)
+ {
+ case Anamorphic.None:
+ nativeJob.anamorphic.mode = 0;
+
+ if (profile.KeepDisplayAspect)
+ {
+ if (profile.Width == 0 && profile.Height == 0 || profile.Width == 0)
+ {
+ width = (int)((double)height * this.GetTitle(job.Title).AspectRatio);
+ }
+ else if (profile.Height == 0)
+ {
+ height = (int)((double)width / this.GetTitle(job.Title).AspectRatio);
+ }
+ }
+
+ nativeJob.anamorphic.keep_display_aspect = profile.KeepDisplayAspect ? 1 : 0;
+ break;
+ case Anamorphic.Strict:
+ nativeJob.anamorphic.mode = 1;
+ break;
+ case Anamorphic.Loose:
+ nativeJob.anamorphic.mode = 2;
+ break;
+ case Anamorphic.Custom:
+ nativeJob.anamorphic.mode = 3;
+
+ nativeJob.modulus = profile.Modulus;
+
+ if (profile.UseDisplayWidth)
+ {
+ if (profile.KeepDisplayAspect)
+ {
+ height = (int)((double)profile.DisplayWidth / this.GetTitle(job.Title).AspectRatio);
+ }
+
+ nativeJob.anamorphic.dar_width = profile.DisplayWidth;
+ nativeJob.anamorphic.dar_height = height;
+ nativeJob.anamorphic.keep_display_aspect = profile.KeepDisplayAspect ? 1 : 0;
+ }
+ else
+ {
+ nativeJob.anamorphic.par_width = profile.PixelAspectX;
+ nativeJob.anamorphic.par_height = profile.PixelAspectY;
+ nativeJob.anamorphic.keep_display_aspect = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ nativeJob.width = width;
+ nativeJob.height = height;
+
+ nativeJob.maxWidth = profile.MaxWidth;
+ nativeJob.maxHeight = profile.MaxHeight;
+
+ switch (profile.VideoEncoder)
+ {
+ case VideoEncoder.X264:
+ nativeJob.vcodec = NativeConstants.HB_VCODEC_X264;
+ break;
+ case VideoEncoder.Theora:
+ nativeJob.vcodec = NativeConstants.HB_VCODEC_THEORA;
+ break;
+ case VideoEncoder.FFMpeg:
+ nativeJob.vcodec = NativeConstants.HB_VCODEC_FFMPEG;
+ break;
+ default:
+ break;
+ }
+
+ if (profile.VideoEncodeRateType == VideoEncodeRateType.ConstantQuality)
+ {
+ nativeJob.vquality = (float)profile.Quality;
+ nativeJob.vbitrate = 0;
+ }
+ else if (profile.VideoEncodeRateType == VideoEncodeRateType.AverageBitrate)
+ {
+ nativeJob.vquality = -1;
+ nativeJob.vbitrate = profile.VideoBitrate;
+ }
+
+ // vrate
+ // vrate_base
+ // vfr
+ // cfr
+ // areBframes
+ // color_matrix
+ List<hb_audio_s> titleAudio = InteropUtilities.ConvertList<hb_audio_s>(originalTitle.list_audio);
+
+ List<hb_audio_s> audioList = new List<hb_audio_s>();
+ int numTracks = 0;
+ foreach (AudioEncoding encoding in profile.AudioEncodings)
+ {
+ if (encoding.InputNumber == 0)
+ {
+ // Add this encoding for all chosen tracks
+ foreach (int chosenTrack in job.ChosenAudioTracks)
+ {
+ if (titleAudio.Count >= chosenTrack)
+ {
+ audioList.Add(ConvertAudioBack(encoding, titleAudio[chosenTrack - 1], chosenTrack, numTracks++));
+ }
+ }
+ }
+ else if (encoding.InputNumber <= job.ChosenAudioTracks.Count)
+ {
+ // Add this encoding for the specified track, if it exists
+ int trackNumber = job.ChosenAudioTracks[encoding.InputNumber - 1];
+ audioList.Add(ConvertAudioBack(encoding, titleAudio[trackNumber - 1], trackNumber, numTracks++));
+ }
+ }
+
+ NativeList nativeAudioList = InteropUtilities.ConvertListBack<hb_audio_s>(audioList);
+ nativeJob.list_audio = nativeAudioList.ListPtr;
+ allocatedMemory.AddRange(nativeAudioList.AllocatedMemory);
+
+ List<hb_subtitle_s> subtitleList = new List<hb_subtitle_s>();
+
+ if (job.Subtitles != null)
+ {
+ if (job.Subtitles.SourceSubtitles != null && job.Subtitles.SourceSubtitles.Count > 0)
+ {
+ List<hb_subtitle_s> titleSubtitles = InteropUtilities.ConvertList<hb_subtitle_s>(originalTitle.list_subtitle);
+
+ foreach (SourceSubtitle sourceSubtitle in job.Subtitles.SourceSubtitles)
+ {
+ if (sourceSubtitle.TrackNumber == 0)
+ {
+ // Use subtitle search.
+ nativeJob.select_subtitle_config.force = sourceSubtitle.Forced ? 1 : 0;
+ nativeJob.select_subtitle_config.default_track = sourceSubtitle.Default ? 1 : 0;
+
+ if (!sourceSubtitle.BurnedIn && profile.OutputFormat == OutputFormat.Mkv)
+ {
+ nativeJob.select_subtitle_config.dest = hb_subtitle_config_s_subdest.PASSTHRUSUB;
+ }
+
+ nativeJob.indepth_scan = 1;
+ }
+ else
+ {
+ // Use specified subtitle.
+ hb_subtitle_s nativeSubtitle = titleSubtitles[sourceSubtitle.TrackNumber - 1];
+ nativeSubtitle.config.force = sourceSubtitle.Forced ? 1 : 0;
+ nativeSubtitle.config.default_track = sourceSubtitle.Default ? 1 : 0;
+
+ if (!sourceSubtitle.BurnedIn && profile.OutputFormat == OutputFormat.Mkv && nativeSubtitle.format == hb_subtitle_s_subtype.PICTURESUB)
+ {
+ nativeSubtitle.config.dest = hb_subtitle_config_s_subdest.PASSTHRUSUB;
+ }
+
+ subtitleList.Add(nativeSubtitle);
+ }
+ }
+ }
+
+ if (job.Subtitles.SrtSubtitles != null)
+ {
+ foreach (SrtSubtitle srtSubtitle in job.Subtitles.SrtSubtitles)
+ {
+ hb_subtitle_s nativeSubtitle = new hb_subtitle_s();
+ nativeSubtitle.id = subtitleList.Count << 8 | 0xFF;
+ nativeSubtitle.iso639_2 = srtSubtitle.LanguageCode;
+ nativeSubtitle.lang = LanguageCodes.Decode(srtSubtitle.LanguageCode);
+ nativeSubtitle.source = hb_subtitle_s_subsource.SRTSUB;
+ nativeSubtitle.format = hb_subtitle_s_subtype.TEXTSUB;
+
+ nativeSubtitle.config.src_codeset = srtSubtitle.CharacterCode;
+ nativeSubtitle.config.src_filename = srtSubtitle.FileName;
+ nativeSubtitle.config.offset = srtSubtitle.Offset;
+ nativeSubtitle.config.dest = hb_subtitle_config_s_subdest.PASSTHRUSUB;
+ nativeSubtitle.config.default_track = srtSubtitle.Default ? 1 : 0;
+
+ subtitleList.Add(nativeSubtitle);
+ }
+ }
+ }
+
+ NativeList nativeSubtitleList = InteropUtilities.ConvertListBack<hb_subtitle_s>(subtitleList);
+ nativeJob.list_subtitle = nativeSubtitleList.ListPtr;
+ allocatedMemory.AddRange(nativeSubtitleList.AllocatedMemory);
+
+ if (profile.OutputFormat == OutputFormat.Mp4)
+ {
+ nativeJob.mux = NativeConstants.HB_MUX_MP4;
+ }
+ else
+ {
+ nativeJob.mux = NativeConstants.HB_MUX_MKV;
+ }
+
+ nativeJob.file = job.OutputPath;
+
+ nativeJob.largeFileSize = profile.LargeFile ? 1 : 0;
+ nativeJob.mp4_optimize = profile.Optimize ? 1 : 0;
+ nativeJob.ipod_atom = profile.IPod5GSupport ? 1 : 0;
+
+ string x264Options = profile.X264Options ?? string.Empty;
+ if (profile.TwoPass)
+ {
+ nativeJob.pass = 1;
+
+ if (profile.TurboFirstPass)
+ {
+ if (x264Options == string.Empty)
+ {
+ x264Options = TurboX264Opts;
+ }
+ else
+ {
+ x264Options += ":" + TurboX264Opts;
+ }
+ }
+ }
+
+ nativeJob.x264opts = Marshal.StringToHGlobalAnsi(x264Options);
+ allocatedMemory.Add(nativeJob.x264opts);
+
+ // indepth_scan
+
+ if (title.AngleCount > 1)
+ {
+ nativeJob.angle = job.Angle;
+ }
+
+ // frames_to_skip
+
+ return allocatedMemory;
+ }
+
+ /// <summary>
+ /// Adds a filter to the given filter list.
+ /// </summary>
+ /// <param name="filterList">The filter list to add to.</param>
+ /// <param name="filterType">The type of filter.</param>
+ /// <param name="settings">Settings for the filter.</param>
+ /// <param name="allocatedMemory">The list of allocated memory.</param>
+ private void AddFilter(List<IntPtr> filterList, int filterType, string settings, List<IntPtr> allocatedMemory)
+ {
+ IntPtr settingsNativeString = Marshal.StringToHGlobalAnsi(settings);
+ filterList.Add(HbLib.hb_get_filter_object(filterType, settingsNativeString));
+
+ allocatedMemory.Add(settingsNativeString);
+ }
+
+ /// <summary>
+ /// Gets the title, given the 1-based index.
+ /// </summary>
+ /// <param name="titleIndex">The index of the title (1-based).</param>
+ /// <returns>The requested Title.</returns>
+ private Title GetTitle(int titleIndex)
+ {
+ return this.Titles.SingleOrDefault(title => title.TitleNumber == titleIndex);
+ }
+
+ /// <summary>
+ /// Gets the native title object from the title index.
+ /// </summary>
+ /// <param name="titleIndex">The index of the title (1-based).</param>
+ /// <returns>Gets the native title object for the given index.</returns>
+ private hb_title_s GetOriginalTitle(int titleIndex)
+ {
+ List<hb_title_s> matchingTitles = this.originalTitles.Where(title => title.index == titleIndex).ToList();
+ if (matchingTitles.Count == 0)
+ {
+ throw new ArgumentException("Could not find specified title.");
+ }
+
+ if (matchingTitles.Count > 1)
+ {
+ throw new ArgumentException("Multiple titles matched.");
+ }
+
+ return matchingTitles[0];
+ }
+
+ /// <summary>
+ /// Applies an audio encoding to a native audio encoding base structure.
+ /// </summary>
+ /// <param name="encoding">The encoding to apply.</param>
+ /// <param name="baseStruct">The base native structure.</param>
+ /// <param name="track"></param>
+ /// <param name="outputTrack"></param>
+ /// <returns>The resulting native audio structure.</returns>
+ private hb_audio_s ConvertAudioBack(AudioEncoding encoding, hb_audio_s baseStruct, int track, int outputTrack)
+ {
+ hb_audio_s nativeAudio = baseStruct;
+
+ //nativeAudio.config.input.track = track;
+ nativeAudio.config.output.track = outputTrack;
+
+ switch (encoding.Encoder)
+ {
+ case AudioEncoder.Ac3Passthrough:
+ nativeAudio.config.output.codec = NativeConstants.HB_ACODEC_AC3;
+ break;
+ case AudioEncoder.DtsPassthrough:
+ nativeAudio.config.output.codec = NativeConstants.HB_ACODEC_DCA;
+ break;
+ case AudioEncoder.Faac:
+ nativeAudio.config.output.codec = NativeConstants.HB_ACODEC_FAAC;
+ break;
+ case AudioEncoder.Lame:
+ nativeAudio.config.output.codec = NativeConstants.HB_ACODEC_LAME;
+ break;
+ case AudioEncoder.Vorbis:
+ nativeAudio.config.output.codec = NativeConstants.HB_ACODEC_VORBIS;
+ break;
+ default:
+ break;
+ }
+
+ nativeAudio.config.output.bitrate = encoding.Bitrate;
+ nativeAudio.config.output.dynamic_range_compression = 0.0;
+
+ switch (encoding.Mixdown)
+ {
+ case Mixdown.DolbyProLogicII:
+ nativeAudio.config.output.mixdown = NativeConstants.HB_AMIXDOWN_DOLBYPLII;
+ break;
+ case Mixdown.DolbySurround:
+ nativeAudio.config.output.mixdown = NativeConstants.HB_AMIXDOWN_DOLBY;
+ break;
+ case Mixdown.Mono:
+ nativeAudio.config.output.mixdown = NativeConstants.HB_AMIXDOWN_MONO;
+ break;
+ case Mixdown.SixChannelDiscrete:
+ nativeAudio.config.output.mixdown = NativeConstants.HB_AMIXDOWN_6CH;
+ break;
+ case Mixdown.Stereo:
+ nativeAudio.config.output.mixdown = NativeConstants.HB_AMIXDOWN_STEREO;
+ break;
+ default:
+ break;
+ }
+
+ if (encoding.SampleRate != null)
+ {
+ nativeAudio.config.output.samplerate = (int)(double.Parse(encoding.SampleRate) * 1000);
+ }
+
+ nativeAudio.padding = new byte[24600];
+
+ return nativeAudio;
+ }
+
+ /// <summary>
+ /// Converts a native title to a Title object.
+ /// </summary>
+ /// <param name="title">The native title structure.</param>
+ /// <returns>The managed Title object.</returns>
+ private Title ConvertTitle(hb_title_s title)
+ {
+ var newTitle = new Title
+ {
+ TitleNumber = title.index,
+ Resolution = new Size(title.width, title.height),
+ ParVal = new Size(title.pixel_aspect_width, title.pixel_aspect_height),
+ Duration = TimeSpan.FromSeconds(((double)title.duration) / 90000),
+ AutoCropDimensions = new Cropping
+ {
+ Top = title.crop[0],
+ Bottom = title.crop[1],
+ Left = title.crop[2],
+ Right = title.crop[3]
+ },
+ AspectRatio = title.aspect,
+ AngleCount = title.angle_count
+ };
+
+ int currentSubtitleTrack = 1;
+ List<hb_subtitle_s> subtitleList = InteropUtilities.ConvertList<hb_subtitle_s>(title.list_subtitle);
+ foreach (hb_subtitle_s subtitle in subtitleList)
+ {
+ var newSubtitle = new Subtitle
+ {
+ TrackNumber = currentSubtitleTrack,
+ Language = subtitle.lang,
+ LanguageCode = subtitle.iso639_2
+ };
+
+ if (subtitle.format == hb_subtitle_s_subtype.PICTURESUB)
+ {
+ newSubtitle.SubtitleType = SubtitleType.Picture;
+ }
+ else if (subtitle.format == hb_subtitle_s_subtype.TEXTSUB)
+ {
+ newSubtitle.SubtitleType = SubtitleType.Text;
+ }
+
+ newTitle.Subtitles.Add(newSubtitle);
+
+ currentSubtitleTrack++;
+ }
+
+ int currentAudioTrack = 1;
+ List<hb_audio_s> audioList = InteropUtilities.ConvertList<hb_audio_s>(title.list_audio);
+ foreach (hb_audio_s audio in audioList)
+ {
+ var newAudio = new AudioTrack
+ {
+ TrackNumber = currentAudioTrack,
+ Language = audio.config.lang.simple,
+ LanguageCode = audio.config.lang.iso639_2,
+ Description = audio.config.lang.description
+ };
+
+ newTitle.AudioTracks.Add(newAudio);
+
+ currentAudioTrack++;
+ }
+
+ List<hb_chapter_s> chapterList = InteropUtilities.ConvertList<hb_chapter_s>(title.list_chapter);
+ foreach (hb_chapter_s chapter in chapterList)
+ {
+ var newChapter = new Chapter
+ {
+ ChapterNumber = chapter.index,
+ Duration = TimeSpan.FromSeconds(((double)chapter.duration) / 90000)
+ };
+
+ newTitle.Chapters.Add(newChapter);
+ }
+
+ return newTitle;
+ }
+ }
+}
diff --git a/win/C#/interop/HandBrakeInterop.5.0.ReSharper.user b/win/C#/interop/HandBrakeInterop.5.0.ReSharper.user
new file mode 100644
index 000000000..e258cb794
--- /dev/null
+++ b/win/C#/interop/HandBrakeInterop.5.0.ReSharper.user
@@ -0,0 +1,24 @@
+<Configuration>
+ <SettingsComponent>
+ <string />
+ <integer />
+ <boolean>
+ <setting name="SolutionAnalysisEnabled">False</setting>
+ </boolean>
+ </SettingsComponent>
+ <RecentFiles>
+ <RecentFiles />
+ <RecentEdits />
+ </RecentFiles>
+ <NAntValidationSettings>
+ <NAntPath value="" />
+ </NAntValidationSettings>
+ <UnitTestRunner>
+ <Providers />
+ </UnitTestRunner>
+ <UnitTestRunnerNUnit>
+ <NUnitInstallDir IsNull="False">
+ </NUnitInstallDir>
+ <UseAddins>Never</UseAddins>
+ </UnitTestRunnerNUnit>
+</Configuration> \ No newline at end of file
diff --git a/win/C#/interop/HandBrakeInterop.csproj b/win/C#/interop/HandBrakeInterop.csproj
new file mode 100644
index 000000000..e2d6c0868
--- /dev/null
+++ b/win/C#/interop/HandBrakeInterop.csproj
@@ -0,0 +1,143 @@
+<?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>{F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>HandBrake.Interop</RootNamespace>
+ <AssemblyName>HandBrakeInterop</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </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>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <PlatformTarget>x86</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>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <PlatformTarget>x86</PlatformTarget>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="PresentationCore">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Xaml" />
+ <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">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="DisplayStringAttribute.cs" />
+ <Compile Include="EncodeProgressEventArgs.cs" />
+ <Compile Include="HandBrakeInstance.cs" />
+ <Compile Include="HbLib.cs" />
+ <Compile Include="InteropUtilities.cs" />
+ <Compile Include="Language.cs" />
+ <Compile Include="LanguageCodes.cs" />
+ <Compile Include="MessageLoggedEventArgs.cs" />
+ <Compile Include="Model\Cropping.cs" />
+ <Compile Include="Model\EncodeJob.cs" />
+ <Compile Include="Model\Encoding\Anamorphic.cs" />
+ <Compile Include="Model\Encoding\AudioEncoder.cs" />
+ <Compile Include="Model\Encoding\AudioEncoding.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\EncodingProfile.cs" />
+ <Compile Include="Model\Encoding\Mixdown.cs" />
+ <Compile Include="Model\Encoding\OutputExtension.cs" />
+ <Compile Include="Model\Encoding\OutputFormat.cs" />
+ <Compile Include="Model\Encoding\VideoEncoder.cs" />
+ <Compile Include="Model\Encoding\VideoEncodeRateType.cs" />
+ <Compile Include="Model\Size.cs" />
+ <Compile Include="Model\SourceSubtitle.cs" />
+ <Compile Include="Model\SourceType.cs" />
+ <Compile Include="Model\SrtSubtitle.cs" />
+ <Compile Include="Model\Subtitles.cs" />
+ <Compile Include="NativeList.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ScanProgressEventArgs.cs" />
+ <Compile Include="SourceData\AudioTrack.cs" />
+ <Compile Include="SourceData\Chapter.cs" />
+ <Compile Include="SourceData\Subtitle.cs" />
+ <Compile Include="SourceData\SubtitleType.cs" />
+ <Compile Include="SourceData\Title.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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>
+ -->
+</Project> \ No newline at end of file
diff --git a/win/C#/interop/HandBrakeInterop.sln b/win/C#/interop/HandBrakeInterop.sln
new file mode 100644
index 000000000..1fae7a81c
--- /dev/null
+++ b/win/C#/interop/HandBrakeInterop.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandBrakeInterop", "HandBrakeInterop.csproj", "{F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/win/C#/interop/HandBrakeInterop.suo b/win/C#/interop/HandBrakeInterop.suo
new file mode 100644
index 000000000..beac28595
--- /dev/null
+++ b/win/C#/interop/HandBrakeInterop.suo
Binary files differ
diff --git a/win/C#/interop/HandBrakeInterop2008.sln b/win/C#/interop/HandBrakeInterop2008.sln
new file mode 100644
index 000000000..29a20215d
--- /dev/null
+++ b/win/C#/interop/HandBrakeInterop2008.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandBrakeInterop", "HandBrakeInterop.csproj", "{F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/win/C#/interop/HbLib.cs b/win/C#/interop/HbLib.cs
new file mode 100644
index 000000000..e91632258
--- /dev/null
+++ b/win/C#/interop/HbLib.cs
@@ -0,0 +1,1285 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace HandBrake.Interop
+{
+
+ internal partial class NativeConstants
+ {
+ public const int HB_ACODEC_MASK = 0x00FF00;
+ public const int HB_ACODEC_FAAC = 0x000100;
+ public const int HB_ACODEC_LAME = 0x000200;
+ public const int HB_ACODEC_VORBIS = 0x000400;
+ public const int HB_ACODEC_AC3 = 0x000800;
+ public const int HB_ACODEC_MPGA = 0x001000;
+ public const int HB_ACODEC_LPCM = 0x002000;
+ public const int HB_ACODEC_DCA = 0x004000;
+ public const int HB_ACODEC_FFMPEG = 0x008000;
+ public const int HB_ACODEC_CA_AAC = 0x010000;
+
+ public const int HB_AMIXDOWN_DCA_FORMAT_MASK = 0x00FFF000;
+ public const int HB_AMIXDOWN_A52_FORMAT_MASK = 0x00000FF0;
+ public const int HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK = 0x0000000F;
+ public const int HB_AMIXDOWN_MONO = 0x01000001;
+ public const int HB_AMIXDOWN_STEREO = 0x02002022;
+ public const int HB_AMIXDOWN_DOLBY = 0x042070A2;
+ public const int HB_AMIXDOWN_DOLBYPLII = 0x084094A2;
+ public const int HB_AMIXDOWN_6CH = 0x10089176;
+
+ public const int HB_VCODEC_MASK = 0x0000FF;
+ public const int HB_VCODEC_FFMPEG = 0x000001;
+ public const int HB_VCODEC_X264 = 0x000002;
+ public const int HB_VCODEC_THEORA = 0x000004;
+
+ public const int HB_MUX_MASK = 0xFF0000;
+ public const int HB_MUX_MP4 = 0x010000;
+ public const int HB_MUX_PSP = 0x020000;
+ public const int HB_MUX_AVI = 0x040000;
+ public const int HB_MUX_OGM = 0x080000;
+ public const int HB_MUX_IPOD = 0x100000;
+ public const int HB_MUX_MKV = 0x200000;
+
+ public const int HBTF_NO_IDR = 1 << 0;
+
+ public const int HB_STATE_IDLE = 1;
+ public const int HB_STATE_SCANNING = 2;
+ public const int HB_STATE_SCANDONE = 4;
+ public const int HB_STATE_WORKING = 8;
+ public const int HB_STATE_PAUSED = 16;
+ public const int HB_STATE_WORKDONE = 32;
+ public const int HB_STATE_MUXING = 64;
+
+ public const int HB_ERROR_NONE = 0;
+ public const int HB_ERROR_CANCELED = 1;
+ public const int HB_ERROR_UNKNOWN = 2;
+
+ public const int AUDIO_F_DOLBY = 1 << 31;
+
+ public const int HB_FRAME_IDR = 0x01;
+ public const int HB_FRAME_I = 0x02;
+ public const int HB_FRAME_AUDIO = 0x04;
+ public const int HB_FRAME_P = 0x10;
+ public const int HB_FRAME_B = 0x20;
+ public const int HB_FRAME_BREF = 0x40;
+ public const int HB_FRAME_KEY = 0x0F;
+ public const int HB_FRAME_REF = 0xF0;
+
+ public const int HB_CONFIG_MAX_SIZE = 8192;
+
+ public const int HB_FILTER_DETELECINE = 1;
+ public const int HB_FILTER_DEINTERLACE = 2;
+ public const int HB_FILTER_DEBLOCK = 3;
+ public const int HB_FILTER_DENOISE = 4;
+ public const int HB_FILTER_DECOMB = 5;
+ public const int HB_FILTER_ROTATE = 6;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_anamorphic_substruct
+ {
+ /// int
+ public int mode;
+
+ /// int
+ public int itu_par;
+
+ /// int
+ public int par_width;
+
+ /// int
+ public int par_height;
+
+ /// int
+ public int dar_width;
+
+ /// int
+ public int dar_height;
+
+ /// int
+ public int keep_display_aspect;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_job_s
+ {
+ /// int
+ public int sequence_id;
+
+ /// hb_title_t*
+ public IntPtr title;
+
+ public int feature;
+
+ /// int
+ public int chapter_start;
+
+ /// int
+ public int chapter_end;
+
+ /// int
+ public int chapter_markers;
+
+ /// int[4]
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)]
+ public int[] crop;
+
+ /// int
+ public int deinterlace;
+
+ /// hb_list_t*
+ public IntPtr filters;
+
+ /// int
+ public int width;
+
+ /// int
+ public int height;
+
+ /// int
+ public int keep_ratio;
+
+ /// int
+ public int grayscale;
+
+ public hb_anamorphic_substruct anamorphic;
+
+ public int modulus;
+
+ /// int
+ public int maxWidth;
+
+ /// int
+ public int maxHeight;
+
+ /// int
+ public int vcodec;
+
+ /// float
+ public float vquality;
+
+ /// int
+ public int vbitrate;
+
+ /// int
+ public int vrate;
+
+ /// int
+ public int vrate_base;
+
+ /// int
+ public int vfr;
+
+ /// int
+ public int cfr;
+
+ /// int
+ public int pass;
+
+ /// int
+ public int h264_13;
+
+ /// int
+ public int h264_level;
+
+ /// char*
+ //[MarshalAs(UnmanagedType.LPStr)]
+ //public string x264opts;
+
+ public IntPtr x264opts;
+
+ /// int
+ public int areBframes;
+
+ /// int
+ public int color_matrix;
+
+ /// hb_list_t*
+ public IntPtr list_audio;
+
+ /// hb_list_t*
+ public IntPtr list_subtitle;
+
+ /// int
+ public int mux;
+
+ /// char*
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string file;
+
+ /// int
+ public int largeFileSize;
+
+ /// int
+ public int mp4_optimize;
+
+ /// int
+ public int ipod_atom;
+
+ /// int
+ public int indepth_scan;
+
+ /// hb_subtitle_config_t->hb_subtitle_config_s
+ public hb_subtitle_config_s select_subtitle_config;
+
+ /// int
+ public int angle;
+
+ public int frame_to_start;
+
+ public long pts_to_start;
+
+ /// int
+ public int frame_to_stop;
+
+ /// int64_t->int
+ public long pts_to_stop;
+
+ /// int
+ public int start_at_preview;
+
+ /// int
+ public int seek_points;
+
+ /// uint32_t->unsigned int
+ public uint frames_to_skip;
+
+ // Padding for the part of the struct we don't care about marshaling.
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24644, ArraySubType = UnmanagedType.U1)]
+ public byte[] padding;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_list_s
+ {
+ /// void**
+ public IntPtr items;
+
+ /// int
+ public int items_alloc;
+
+ /// int
+ public int items_count;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_rate_s
+ {
+ /// char*
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string @string;
+
+ /// int
+ public int rate;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct hb_handle_s
+ {
+ public int id;
+
+ /// int
+ public int build;
+
+ /// char[32]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string version;
+
+ /// hb_thread_t*
+ public IntPtr update_thread;
+
+ /// int
+ public int die;
+
+ /// hb_thread_t*
+ public IntPtr main_thread;
+
+ /// int
+ public int pid;
+
+ /// hb_list_t*
+ public IntPtr list_title;
+
+ /// hb_thread_t*
+ public IntPtr scan_thread;
+
+ /// hb_list_t*
+ public IntPtr jobs;
+
+ /// hb_job_t*
+ public IntPtr current_job;
+
+ /// int
+ public int job_count;
+
+ /// int
+ public int job_count_permanent;
+
+ /// int
+ public int work_die;
+
+ /// int
+ public int work_error;
+
+ /// hb_thread_t*
+ public IntPtr work_thread;
+
+ /// int
+ public int cpu_count;
+
+ /// hb_lock_t*
+ public IntPtr state_lock;
+
+ /// hb_state_t->hb_state_s
+ public hb_state_s state;
+
+ /// int
+ public int paused;
+
+ /// hb_lock_t*
+ public IntPtr pause_lock;
+
+ /// int
+ public int scanCount;
+
+ /// hb_interjob_t*
+ public IntPtr interjob;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct hb_chapter_s
+ {
+ /// int
+ public int index;
+
+ /// int
+ public int pgcn;
+
+ /// int
+ public int pgn;
+
+ /// int
+ public int cell_start;
+
+ /// int
+ public int cell_end;
+
+ /// int
+ public int block_start;
+
+ /// int
+ public int block_end;
+
+ /// int
+ public int block_count;
+
+ /// int
+ public int hours;
+
+ /// int
+ public int minutes;
+
+ /// int
+ public int seconds;
+
+ /// uint64_t->unsigned int
+ public ulong duration;
+
+ /// char[1024]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
+ public string title;
+ }
+
+ internal enum hb_subtitle_s_subtype
+ {
+ PICTURESUB,
+
+ TEXTSUB,
+ }
+
+ internal enum hb_subtitle_s_subsource
+ {
+ VOBSUB,
+
+ SRTSUB,
+
+ CC608SUB,
+
+ CC708SUB,
+
+ UTF8SUB,
+
+ TX3GSUB
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct hb_subtitle_s
+ {
+ /// int
+ public int id;
+
+ /// int
+ public int track;
+
+ /// hb_subtitle_config_t->hb_subtitle_config_s
+ public hb_subtitle_config_s config;
+
+ /// hb_subtitle_s_subtype
+ public hb_subtitle_s_subtype format;
+
+ /// hb_subtitle_s_subsource
+ public hb_subtitle_s_subsource source;
+
+ /// char[1024]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
+ public string lang;
+
+ /// char[4]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
+ public string iso639_2;
+
+ /// uint8_t->unsigned char
+ public byte type;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16, ArraySubType = UnmanagedType.U4)]
+ public uint[] palette;
+
+ public int width;
+
+ public int height;
+
+ /// int
+ public int hits;
+
+ /// int
+ public int forced_hits;
+
+ /// hb_fifo_t*
+ public IntPtr fifo_in;
+
+ /// hb_fifo_t*
+ public IntPtr fifo_raw;
+
+ /// hb_fifo_t*
+ public IntPtr fifo_sync;
+
+ /// hb_fifo_t*
+ public IntPtr fifo_out;
+
+ /// hb_mux_data_t*
+ public IntPtr mux_data;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct hb_metadata_s
+ {
+ /// char[255]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
+ public string name;
+
+ /// char[255]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
+ public string artist;
+
+ /// char[255]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
+ public string composer;
+
+ /// char[255]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
+ public string release_date;
+
+ /// char[1024]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
+ public string comment;
+
+ /// char[255]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
+ public string album;
+
+ /// char[255]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
+ public string genre;
+
+ /// uint32_t->unsigned int
+ public uint coverart_size;
+
+ /// uint8_t*
+ public IntPtr coverart;
+ }
+
+ internal enum Anonymous_990d28ea_6cf3_4fbc_8143_4df9513e9550
+ {
+ HB_DVD_TYPE,
+
+ HB_STREAM_TYPE,
+ }
+
+ internal enum Anonymous_618ebeca_0ad9_4a71_9a49_18e50ac2e9db
+ {
+ /// HB_MPEG2_PS_DEMUXER -> 0
+ HB_MPEG2_PS_DEMUXER = 0,
+
+ HB_MPEG2_TS_DEMUXER,
+
+ HB_NULL_DEMUXER,
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct hb_title_s
+ {
+ /// Anonymous_990d28ea_6cf3_4fbc_8143_4df9513e9550
+ public Anonymous_990d28ea_6cf3_4fbc_8143_4df9513e9550 type;
+
+ /// char[1024]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
+ public string dvd;
+
+ /// char[1024]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
+ public string name;
+
+ //public fixed byte dvd[1024];
+
+ //public fixed byte name[1024];
+
+ /// int
+ public int index;
+
+ /// int
+ public int vts;
+
+ /// int
+ public int ttn;
+
+ /// int
+ public int cell_start;
+
+ /// int
+ public int cell_end;
+
+ /// int
+ public int block_start;
+
+ /// int
+ public int block_end;
+
+ /// int
+ public int block_count;
+
+ /// int
+ public int angle_count;
+
+ /// int
+ public int hours;
+
+ /// int
+ public int minutes;
+
+ /// int
+ public int seconds;
+
+ /// uint64_t->unsigned int
+ public ulong duration;
+
+ /// double
+ public double aspect;
+
+ /// double
+ public double container_aspect;
+
+ /// int
+ public int width;
+
+ /// int
+ public int height;
+
+ /// int
+ public int pixel_aspect_width;
+
+ /// int
+ public int pixel_aspect_height;
+
+ /// int
+ public int rate;
+
+ /// int
+ public int rate_base;
+
+ /// int[4]
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)]
+ public int[] crop;
+
+ //public fixed int crop[4];
+
+ /// Anonymous_618ebeca_0ad9_4a71_9a49_18e50ac2e9db
+ public Anonymous_618ebeca_0ad9_4a71_9a49_18e50ac2e9db demuxer;
+
+ /// int
+ public int detected_interlacing;
+
+ /// int
+ public int video_id;
+
+ /// int
+ public int video_codec;
+
+ /// int
+ public int video_codec_param;
+
+ /// char*
+ public IntPtr video_codec_name;
+
+ /// int
+ public int video_bitrate;
+
+ /// char*
+ public IntPtr container_name;
+
+ /// int
+ public int data_rate;
+
+ /// hb_metadata_t*
+ public IntPtr metadata;
+
+ /// hb_list_t*
+ public IntPtr list_chapter;
+
+ /// hb_list_t*
+ public IntPtr list_audio;
+
+ /// hb_list_t*
+ public IntPtr list_subtitle;
+
+ /// hb_job_t*
+ public IntPtr job;
+
+ /// uint32_t->unsigned int
+ public uint flags;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_state_scanning_s
+ {
+ /// int
+ public int title_cur;
+
+ /// int
+ public int title_count;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_state_working_s
+ {
+ /// float
+ public float progress;
+
+ /// int
+ public int job_cur;
+
+ /// int
+ public int job_count;
+
+ /// float
+ public float rate_cur;
+
+ /// float
+ public float rate_avg;
+
+ /// int
+ public int hours;
+
+ /// int
+ public int minutes;
+
+ /// int
+ public int seconds;
+
+ /// int
+ public int sequence_id;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_state_workdone_s
+ {
+ /// int
+ public int error;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_state_muxing_s
+ {
+ /// float
+ public float progress;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct hb_state_param_u
+ {
+ [FieldOffset(0)]
+ public hb_state_scanning_s scanning;
+
+ [FieldOffset(0)]
+ public hb_state_working_s working;
+
+ [FieldOffset(0)]
+ public hb_state_workdone_s workdone;
+
+ [FieldOffset(0)]
+ public hb_state_muxing_s muxing;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_state_s
+ {
+
+ /// int
+ public int state;
+ public hb_state_param_u param;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_audio_s
+ {
+ /// int
+ public int id;
+
+ /// hb_audio_config_t->hb_audio_config_s
+ public hb_audio_config_s config;
+
+ // Padding for the part of the struct we don't care about marshaling.
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24600, ArraySubType = UnmanagedType.U1)]
+ public byte[] padding;
+
+ /// Anonymous_e6c7b779_b5a3_4e80_9fa8_13619d14f545
+ //public Anonymous_e6c7b779_b5a3_4e80_9fa8_13619d14f545 priv;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_audio_config_s
+ {
+ public hb_audio_config_output_s output;
+ public hb_audio_config_input_s input;
+
+ /// Anonymous_a0a59d69_d9a4_4003_a198_f7c51511e31d
+ public Anonymous_a0a59d69_d9a4_4003_a198_f7c51511e31d flags;
+
+ public hb_audio_config_lang_s lang;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_audio_config_output_s
+ {
+ /// int
+ public int track;
+
+ /// uint32_t->unsigned int
+ public uint codec;
+
+ /// int
+ public int samplerate;
+
+ /// int
+ public int bitrate;
+
+ /// int
+ public int mixdown;
+
+ /// double
+ public double dynamic_range_compression;
+
+ /// char*
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string name;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_audio_config_input_s
+ {
+ /// int
+ public int track;
+
+ /// uint32_t->unsigned int
+ public uint codec;
+
+ /// uint32_t->unsigned int
+ public uint codec_param;
+
+ /// uint32_t->unsigned int
+ public uint version;
+
+ /// uint32_t->unsigned int
+ public uint mode;
+
+ /// int
+ public int samplerate;
+
+ /// int
+ public int bitrate;
+
+ /// int
+ public int channel_layout;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct Anonymous_a0a59d69_d9a4_4003_a198_f7c51511e31d
+ {
+ /// int
+ [FieldOffset(0)]
+ public int ac3;
+
+ /// int
+ [FieldOffset(0)]
+ public int dca;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct hb_audio_config_lang_s
+ {
+ /// char[1024]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
+ public string description;
+
+ /// char[1024]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
+ public string simple;
+
+ /// char[4]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
+ public string iso639_2;
+
+ /// uint8_t->unsigned char
+ public byte type;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_mixdown_s
+ {
+ /// char*
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string human_readable_name;
+
+ /// char*
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string internal_name;
+
+ /// char*
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string short_name;
+
+ /// int
+ public int amixdown;
+ }
+
+ internal enum hb_subtitle_config_s_subdest
+ {
+ RENDERSUB,
+
+ PASSTHRUSUB,
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct hb_subtitle_config_s
+ {
+ /// hb_subtitle_config_s_subdest
+ public hb_subtitle_config_s_subdest dest;
+
+ /// int
+ public int force;
+
+ /// int
+ public int default_track;
+
+ /// char[128]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
+ public string src_filename;
+
+ /// char[40]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
+ public string src_codeset;
+
+ /// int64_t->int
+ public long offset;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_fifo_s
+ {
+ /// hb_lock_t*
+ public IntPtr @lock;
+
+ /// uint32_t->unsigned int
+ public uint capacity;
+
+ /// uint32_t->unsigned int
+ public uint size;
+
+ /// uint32_t->unsigned int
+ public uint buffer_size;
+
+ /// hb_buffer_t*
+ public IntPtr first;
+
+ /// hb_buffer_t*
+ public IntPtr last;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_lock_s
+ {
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_buffer_s
+ {
+ /// int
+ public int size;
+
+ /// int
+ public int alloc;
+
+ /// uint8_t*
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string data;
+
+ /// int
+ public int cur;
+
+ /// int64_t->int
+ public long sequence;
+
+ /// int
+ public int id;
+
+ /// int64_t->int
+ public long start;
+
+ /// int64_t->int
+ public long stop;
+
+ /// int
+ public int new_chap;
+
+ /// uint8_t->unsigned char
+ public byte frametype;
+
+ /// uint16_t->unsigned int
+ public uint flags;
+
+ /// int64_t->int
+ public long renderOffset;
+
+ /// int
+ public int x;
+
+ /// int
+ public int y;
+
+ /// int
+ public int width;
+
+ /// int
+ public int height;
+
+ /// hb_buffer_t*
+ public IntPtr sub;
+
+ /// hb_buffer_t*
+ public IntPtr next;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_mux_data_s
+ {
+ /// MP4TrackId->uint32_t->unsigned int
+ public uint track;
+
+ /// uint8_t->unsigned char
+ public byte subtitle;
+
+ /// int
+ public int sub_format;
+
+ /// uint64_t->unsigned int
+ public ulong sum_dur;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_interjob_s
+ {
+ /// int
+ public int last_job;
+
+ /// int
+ public int frame_count;
+
+ /// uint64_t->unsigned int
+ public ulong total_time;
+
+ /// int
+ public int render_dropped;
+
+ /// int
+ public int vrate;
+
+ /// int
+ public int vrate_base;
+
+ /// hb_subtitle_t*
+ public IntPtr select_subtitle;
+ }
+
+ /// Return Type: void
+ ///param0: void*
+ internal delegate void hb_thread_s_function(IntPtr param0);
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct hb_thread_s
+ {
+ /// char*
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string name;
+
+ /// int
+ public int priority;
+
+ /// hb_thread_s_function
+ public hb_thread_s_function AnonymousMember1;
+
+ /// void*
+ public IntPtr arg;
+
+ /// hb_lock_t*
+ public IntPtr @lock;
+
+ /// int
+ public int exited;
+
+ /// pthread_t->ptw32_handle_t->Anonymous_55c509b5_bbf2_4788_a684_ac1bd0056655
+ public ptw32_handle_t thread;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct ptw32_handle_t
+ {
+ /// void*
+ public IntPtr p;
+
+ /// unsigned int
+ public uint x;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void LoggingCallback(string message);
+
+ internal partial class HbLib
+ {
+ [DllImport("hb.dll", EntryPoint = "hb_register_logger", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_register_logger(LoggingCallback callback);
+
+ [DllImport("hb.dll", EntryPoint = "hb_register_error_handler", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_register_error_handler(LoggingCallback callback);
+
+ /// Return Type: hb_handle_t*
+ ///verbose: int
+ ///update_check: int
+ [DllImport("hb.dll", EntryPoint = "hb_init", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_init(int verbose, int update_check);
+
+
+ /// Return Type: hb_handle_t*
+ ///verbose: int
+ ///update_check: int
+ [DllImport("hb.dll", EntryPoint = "hb_init_dl", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_init_dl(int verbose, int update_check);
+
+
+ /// Return Type: char*
+ ///param0: hb_handle_t*
+ [DllImport("hb.dll", EntryPoint = "hb_get_version", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_get_version(ref hb_handle_s param0);
+
+
+ /// Return Type: int
+ ///param0: hb_handle_t*
+ [DllImport("hb.dll", EntryPoint = "hb_get_build", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_get_build(ref hb_handle_s param0);
+
+
+ /// Return Type: int
+ ///h: hb_handle_t*
+ ///version: char**
+ [DllImport("hb.dll", EntryPoint = "hb_check_update", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_check_update(ref hb_handle_s h, ref IntPtr version);
+
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ ///param1: int
+ [DllImport("hb.dll", EntryPoint = "hb_set_cpu_count", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_set_cpu_count(ref hb_handle_s param0, int param1);
+
+
+ /// Return Type: char*
+ ///path: char*
+ [DllImport("hb.dll", EntryPoint = "hb_dvd_name", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_dvd_name(IntPtr path);
+
+
+ /// Return Type: void
+ ///enable: int
+ [DllImport("hb.dll", EntryPoint = "hb_dvd_set_dvdnav", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_dvd_set_dvdnav(int enable);
+
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ ///path: char*
+ ///title_index: int
+ ///preview_count: int
+ ///store_previews: int
+ [DllImport("hb.dll", EntryPoint = "hb_scan", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_scan(IntPtr hbHandle, [In] [MarshalAs(UnmanagedType.LPStr)] string path, int title_index, int preview_count, int store_previews);
+
+
+ /// Return Type: hb_list_t*
+ ///param0: hb_handle_t*
+ [DllImport("hb.dll", EntryPoint = "hb_get_titles", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_get_titles(IntPtr hbHandle);
+
+
+ /// Return Type: int
+ ///buf: hb_buffer_t*
+ ///width: int
+ ///height: int
+ ///color_equal: int
+ ///color_diff: int
+ ///threshold: int
+ ///prog_equal: int
+ ///prog_diff: int
+ ///prog_threshold: int
+ [DllImport("hb.dll", EntryPoint = "hb_detect_comb", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_detect_comb(ref hb_buffer_s buf, int width, int height, int color_equal, int color_diff, int threshold, int prog_equal, int prog_diff, int prog_threshold);
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_preview_by_index", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_get_preview_by_index(IntPtr hbHandle, int title_index, int picture, IntPtr buffer);
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ ///param1: hb_title_t*
+ ///param2: int
+ ///param3: uint8_t*
+ [DllImport("hb.dll", EntryPoint = "hb_get_preview", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_get_preview(IntPtr hbHandle, ref hb_title_s title, int preview, IntPtr buffer);
+
+
+ /// Return Type: void
+ ///param0: hb_job_t*
+ ///ratio: double
+ ///pixels: int
+ [DllImport("hb.dll", EntryPoint = "hb_set_size", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_set_size(ref hb_job_s param0, double ratio, int pixels);
+
+ [DllImport("hb.dll", EntryPoint = "hb_set_anamorphic_size_by_index", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_set_anamorphic_size_by_index(IntPtr hbHandle, int title_index, ref int output_width, ref int output_height, ref int output_par_width, ref int output_par_height);
+
+ /// Return Type: void
+ ///param0: hb_job_t*
+ ///output_width: int*
+ ///output_height: int*
+ ///output_par_width: int*
+ ///output_par_height: int*
+ [DllImport("hb.dll", EntryPoint = "hb_set_anamorphic_size", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_set_anamorphic_size(ref hb_job_s job, ref int output_width, ref int output_height, ref int output_par_width, ref int output_par_height);
+
+
+ /// Return Type: int
+ ///param0: hb_handle_t*
+ [DllImport("hb.dll", EntryPoint = "hb_count", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_count(IntPtr hbHandle);
+
+
+ /// Return Type: hb_job_t*
+ ///param0: hb_handle_t*
+ ///param1: int
+ [DllImport("hb.dll", EntryPoint = "hb_job", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_job(IntPtr hbHandle, int jobIndex);
+
+ [DllImport("hb.dll", EntryPoint = "hb_set_chapter_name", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_set_chapter_name(IntPtr hbHandle, int title_index, int chapter_index, [In] [MarshalAs(UnmanagedType.LPStr)] string chapter_name);
+
+ [DllImport("hb.dll", EntryPoint = "hb_set_job", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_set_job(IntPtr hbHandle, int title_index, ref hb_job_s job);
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ ///param1: hb_job_t*
+ [DllImport("hb.dll", EntryPoint = "hb_add", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_add(IntPtr hbHandle, ref hb_job_s job);
+
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ ///param1: hb_job_t*
+ [DllImport("hb.dll", EntryPoint = "hb_rem", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_rem(IntPtr hbHandle, IntPtr job);
+
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ [DllImport("hb.dll", EntryPoint = "hb_start", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_start(IntPtr hbHandle);
+
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ [DllImport("hb.dll", EntryPoint = "hb_pause", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_pause(IntPtr hbHandle);
+
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ [DllImport("hb.dll", EntryPoint = "hb_resume", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_resume(IntPtr hbHandle);
+
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ [DllImport("hb.dll", EntryPoint = "hb_stop", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_stop(IntPtr hbHandle);
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_filter_object", CallingConvention = CallingConvention.Cdecl)]
+ //public static extern IntPtr hb_get_filter_object(int filter_id, [In] [MarshalAs(UnmanagedType.LPStr)] string settings);
+ public static extern IntPtr hb_get_filter_object(int filter_id, IntPtr settings);
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ ///param1: hb_state_t*
+ [DllImport("hb.dll", EntryPoint = "hb_get_state", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_get_state(IntPtr hbHandle, ref hb_state_s state);
+
+
+ /// Return Type: void
+ ///param0: hb_handle_t*
+ ///param1: hb_state_t*
+ [DllImport("hb.dll", EntryPoint = "hb_get_state2", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_get_state2(ref hb_handle_s param0, ref hb_state_s param1);
+
+
+ /// Return Type: int
+ ///param0: hb_handle_t*
+ [DllImport("hb.dll", EntryPoint = "hb_get_scancount", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_get_scancount(ref hb_handle_s param0);
+
+
+ /// Return Type: void
+ ///param0: hb_handle_t**
+ [DllImport("hb.dll", EntryPoint = "hb_close", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_close(IntPtr hbHandle);
+
+ [DllImport("hb.dll", EntryPoint = "hb_global_close", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_global_close();
+ }
+}
diff --git a/win/C#/interop/InteropUtilities.cs b/win/C#/interop/InteropUtilities.cs
new file mode 100644
index 000000000..d53c68883
--- /dev/null
+++ b/win/C#/interop/InteropUtilities.cs
@@ -0,0 +1,120 @@
+namespace HandBrake.Interop
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Runtime.InteropServices;
+
+ /// <summary>
+ /// Helper utilities for native interop.
+ /// </summary>
+ public static class InteropUtilities
+ {
+ /// <summary>
+ /// Reads the given native structure pointer.
+ /// </summary>
+ /// <typeparam name="T">The type to convert the structure to.</typeparam>
+ /// <param name="structPtr">The pointer to the native structure.</param>
+ /// <returns>The converted structure.</returns>
+ public static T ReadStructure<T>(IntPtr structPtr)
+ {
+ return (T)Marshal.PtrToStructure(structPtr, typeof(T));
+ }
+
+ /// <summary>
+ /// Converts the given native HandBrake list to a managed list.
+ /// </summary>
+ /// <typeparam name="T">The type of structure in the list.</typeparam>
+ /// <param name="listPtr">The pointer to the native list.</param>
+ /// <returns>The converted managed list.</returns>
+ public static List<T> ConvertList<T>(IntPtr listPtr)
+ {
+ List<T> returnList = new List<T>();
+ hb_list_s itemList = ReadStructure<hb_list_s>(listPtr);
+
+ for (int i = 0; i < itemList.items_count; i++)
+ {
+ IntPtr itemPtr = Marshal.ReadIntPtr(itemList.items, i * Marshal.SizeOf(typeof(IntPtr)));
+ returnList.Add(ReadStructure<T>(itemPtr));
+ }
+
+ return returnList;
+ }
+
+ /// <summary>
+ /// Creates a native HandBrake list from the given managed list of pointers.
+ /// </summary>
+ /// <param name="list">The managed list to convert.</param>
+ /// <returns>The converted native list.</returns>
+ public static NativeList CreateIntPtrList(List<IntPtr> list)
+ {
+ NativeList returnList = new NativeList();
+ int intSize = Marshal.SizeOf(typeof(IntPtr));
+
+ IntPtr nativeListInternal = Marshal.AllocHGlobal(list.Count * intSize);
+ returnList.AllocatedMemory.Add(nativeListInternal);
+ for (int i = 0; i < list.Count; i++)
+ {
+ Marshal.WriteIntPtr(nativeListInternal, i * intSize, list[i]);
+ }
+
+ hb_list_s nativeListStruct = new hb_list_s();
+ nativeListStruct.items = nativeListInternal;
+ nativeListStruct.items_alloc = list.Count;
+ nativeListStruct.items_count = list.Count;
+
+ IntPtr nativeListStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_list_s)));
+ Marshal.StructureToPtr(nativeListStruct, nativeListStructPtr, false);
+
+ returnList.ListPtr = nativeListStructPtr;
+ return returnList;
+ }
+
+ /// <summary>
+ /// Creates a native HandBrake list from the given managed list of structures.
+ /// </summary>
+ /// <typeparam name="T">The type of structures in the list.</typeparam>
+ /// <param name="list">The managed list to convert.</param>
+ /// <returns>The converted native list.</returns>
+ public static NativeList ConvertListBack<T>(List<T> list)
+ {
+ NativeList returnList = new NativeList();
+ int intSize = Marshal.SizeOf(typeof(IntPtr));
+
+ IntPtr nativeListInternal = Marshal.AllocHGlobal(list.Count * intSize);
+ returnList.AllocatedMemory.Add(nativeListInternal);
+ for (int i = 0; i < list.Count; i++)
+ {
+ IntPtr itemPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)));
+ returnList.AllocatedMemory.Add(itemPtr);
+ Marshal.StructureToPtr(list[i], itemPtr, false);
+
+ Marshal.WriteIntPtr(nativeListInternal, i * intSize, itemPtr);
+ }
+
+ hb_list_s nativeListStruct = new hb_list_s();
+ nativeListStruct.items = nativeListInternal;
+ nativeListStruct.items_alloc = list.Count;
+ nativeListStruct.items_count = list.Count;
+
+ IntPtr nativeListStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_list_s)));
+ Marshal.StructureToPtr(nativeListStruct, nativeListStructPtr, false);
+
+ returnList.ListPtr = nativeListStructPtr;
+ return returnList;
+ }
+
+ /// <summary>
+ /// Frees all the memory locations in the given list.
+ /// </summary>
+ /// <param name="memoryList">The list of memory locations to free.</param>
+ public static void FreeMemory(List<IntPtr> memoryList)
+ {
+ foreach (IntPtr memoryLocation in memoryList)
+ {
+ Marshal.FreeHGlobal(memoryLocation);
+ }
+ }
+ }
+}
diff --git a/win/C#/interop/Language.cs b/win/C#/interop/Language.cs
new file mode 100644
index 000000000..609a4ec64
--- /dev/null
+++ b/win/C#/interop/Language.cs
@@ -0,0 +1,38 @@
+namespace HandBrake.Interop
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ /// <summary>
+ /// Represents a language.
+ /// </summary>
+ public class Language
+ {
+ /// <summary>
+ /// Initializes a new instance of the Language class.
+ /// </summary>
+ /// <param name="code">The code for the langauge.</param>
+ public Language(string code)
+ {
+ this.Code = code;
+ }
+
+ /// <summary>
+ /// Gets the friendly name of the language.
+ /// </summary>
+ public string Name
+ {
+ get
+ {
+ return LanguageCodes.Decode(this.Code);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the language code.
+ /// </summary>
+ public string Code { get; set; }
+ }
+}
diff --git a/win/C#/interop/LanguageCodes.cs b/win/C#/interop/LanguageCodes.cs
new file mode 100644
index 000000000..0d45cc1da
--- /dev/null
+++ b/win/C#/interop/LanguageCodes.cs
@@ -0,0 +1,255 @@
+namespace HandBrake.Interop
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ /// <summary>
+ /// Contains utilities for converting language codes.
+ /// </summary>
+ public static class LanguageCodes
+ {
+ /// <summary>
+ /// The map of language codes to friendly names.
+ /// </summary>
+ private static Dictionary<string, string> languageMap;
+
+ /// <summary>
+ /// Gets the map of language codes to friendly names.
+ /// </summary>
+ private static Dictionary<string, string> LanguageMap
+ {
+ get
+ {
+ if (languageMap == null)
+ {
+ languageMap = new Dictionary<string, string>
+ {
+ {"und", "Unspecified"},
+ {"eng", "English"},
+ {"deu", "Deutsch"},
+ {"fra", "Français"},
+ {"spa", "Español"},
+ {"rus", "Russian"},
+ {"aar", "Afar"},
+ {"abk", "Abkhazian"},
+ {"afr", "Afrikaans"},
+ {"aka", "Akan"},
+ {"sqi", "Albanian"},
+ {"amh", "Amharic"},
+ {"ara", "Arabic"},
+ {"arg", "Aragonese"},
+ {"hye", "Armenian"},
+ {"asm", "Assamese"},
+ {"ava", "Avaric"},
+ {"ave", "Avestan"},
+ {"aym", "Aymara"},
+ {"aze", "Azerbaijani"},
+ {"bak", "Bashkir"},
+ {"bam", "Bambara"},
+ {"eus", "Basque"},
+ {"bel", "Belarusian"},
+ {"ben", "Bengali"},
+ {"bih", "Bihari"},
+ {"bis", "Bislama"},
+ {"bos", "Bosnian"},
+ {"bre", "Breton"},
+ {"bul", "Bulgarian"},
+ {"mya", "Burmese"},
+ {"cat", "Catalan"},
+ {"cha", "Chamorro"},
+ {"che", "Chechen"},
+ {"zho", "Chinese"},
+ {"chu", "Church Slavic"},
+ {"chv", "Chuvash"},
+ {"cor", "Cornish"},
+ {"cos", "Corsican"},
+ {"cre", "Cree"},
+ {"ces", "Czech"},
+ {"dan", "Dansk"},
+ {"div", "Divehi"},
+ {"nld", "Nederlands"},
+ {"dzo", "Dzongkha"},
+ {"epo", "Esperanto"},
+ {"est", "Estonian"},
+ {"ewe", "Ewe"},
+ {"fao", "Faroese"},
+ {"fij", "Fijian"},
+ {"fin", "Suomi"},
+ {"fry", "Western Frisian"},
+ {"ful", "Fulah"},
+ {"kat", "Georgian"},
+ {"gla", "Gaelic (Scots)"},
+ {"gle", "Irish"},
+ {"glg", "Galician"},
+ {"glv", "Manx"},
+ {"ell", "Greek Modern"},
+ {"grn", "Guarani"},
+ {"guj", "Gujarati"},
+ {"hat", "Haitian"},
+ {"hau", "Hausa"},
+ {"heb", "Hebrew"},
+ {"her", "Herero"},
+ {"hin", "Hindi"},
+ {"hmo", "Hiri Motu"},
+ {"hun", "Magyar"},
+ {"ibo", "Igbo"},
+ {"isl", "Islenska"},
+ {"ido", "Ido"},
+ {"iii", "Sichuan Yi"},
+ {"iku", "Inuktitut"},
+ {"ile", "Interlingue"},
+ {"ina", "Interlingua"},
+ {"ind", "Indonesian"},
+ {"ipk", "Inupiaq"},
+ {"ita", "Italiano"},
+ {"jav", "Javanese"},
+ {"jpn", "Japanese"},
+ {"kal", "Kalaallisut"},
+ {"kan", "Kannada"},
+ {"kas", "Kashmiri"},
+ {"kau", "Kanuri"},
+ {"kaz", "Kazakh"},
+ {"khm", "Central Khmer"},
+ {"kik", "Kikuyu"},
+ {"kin", "Kinyarwanda"},
+ {"kir", "Kirghiz"},
+ {"kom", "Komi"},
+ {"kon", "Kongo"},
+ {"kor", "Korean"},
+ {"kua", "Kuanyama"},
+ {"kur", "Kurdish"},
+ {"lao", "Lao"},
+ {"lat", "Latin"},
+ {"lav", "Latvian"},
+ {"lim", "Limburgan"},
+ {"lin", "Lingala"},
+ {"lit", "Lithuanian"},
+ {"ltz", "Luxembourgish"},
+ {"lub", "Luba-Katanga"},
+ {"lug", "Ganda"},
+ {"mkd", "Macedonian"},
+ {"mah", "Marshallese"},
+ {"mal", "Malayalam"},
+ {"mri", "Maori"},
+ {"mar", "Marathi"},
+ {"msa", "Malay"},
+ {"mlg", "Malagasy"},
+ {"mlt", "Maltese"},
+ {"mol", "Moldavian"},
+ {"mon", "Mongolian"},
+ {"nau", "Nauru"},
+ {"nav", "Navajo"},
+ {"nbl", "Ndebele, South"},
+ {"nde", "Ndebele, North"},
+ {"ndo", "Ndonga"},
+ {"nep", "Nepali"},
+ {"nno", "Norwegian Nynorsk"},
+ {"nob", "Norwegian Bokmål"},
+ {"nor", "Norsk"},
+ {"nya", "Chichewa; Nyanja"},
+ {"oci", "Occitan"},
+ {"oji", "Ojibwa"},
+ {"ori", "Oriya"},
+ {"orm", "Oromo"},
+ {"oss", "Ossetian"},
+ {"pan", "Panjabi"},
+ {"fas", "Persian"},
+ {"pli", "Pali"},
+ {"pol", "Polish"},
+ {"por", "Portugues"},
+ {"pus", "Pushto"},
+ {"que", "Quechua"},
+ {"roh", "Romansh"},
+ {"ron", "Romanian"},
+ {"run", "Rundi"},
+ {"sag", "Sango"},
+ {"san", "Sanskrit"},
+ {"srp", "Serbian"},
+ {"hrv", "Hrvatski"},
+ {"sin", "Sinhala"},
+ {"slk", "Slovak"},
+ {"slv", "Slovenian"},
+ {"sme", "Northern Sami"},
+ {"smo", "Samoan"},
+ {"sna", "Shona"},
+ {"snd", "Sindhi"},
+ {"som", "Somali"},
+ {"sot", "Sotho Southern"},
+ {"srd", "Sardinian"},
+ {"ssw", "Swati"},
+ {"sun", "Sundanese"},
+ {"swa", "Swahili"},
+ {"swe", "Svenska"},
+ {"tah", "Tahitian"},
+ {"tam", "Tamil"},
+ {"tat", "Tatar"},
+ {"tel", "Telugu"},
+ {"tgk", "Tajik"},
+ {"tgl", "Tagalog"},
+ {"tha", "Thai"},
+ {"bod", "Tibetan"},
+ {"tir", "Tigrinya"},
+ {"ton", "Tonga"},
+ {"tsn", "Tswana"},
+ {"tso", "Tsonga"},
+ {"tuk", "Turkmen"},
+ {"tur", "Turkish"},
+ {"twi", "Twi"},
+ {"uig", "Uighur"},
+ {"ukr", "Ukrainian"},
+ {"urd", "Urdu"},
+ {"uzb", "Uzbek"},
+ {"ven", "Venda"},
+ {"vie", "Vietnamese"},
+ {"vol", "Volapük"},
+ {"cym", "Welsh"},
+ {"wln", "Walloon"},
+ {"wol", "Wolof"},
+ {"xho", "Xhosa"},
+ {"yid", "Yiddish"},
+ {"yor", "Yoruba"},
+ {"zha", "Zhuang"},
+ {"zul", "Zulu"}
+ };
+ }
+
+ return languageMap;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of all languages.
+ /// </summary>
+ public static IList<Language> Languages
+ {
+ get
+ {
+ List<Language> languages = new List<Language>();
+
+ foreach (string languageCode in LanguageMap.Keys)
+ {
+ languages.Add(new Language(languageCode));
+ }
+
+ return languages;
+ }
+ }
+
+ /// <summary>
+ /// Gives the friendly name of the language with the given code.
+ /// </summary>
+ /// <param name="languageCode">The language code.</param>
+ /// <returns>The friendly name of the language.</returns>
+ public static string Decode(string languageCode)
+ {
+ if (LanguageMap.ContainsKey(languageCode))
+ {
+ return LanguageMap[languageCode];
+ }
+
+ return "Unknown";
+ }
+ }
+}
diff --git a/win/C#/interop/MessageLoggedEventArgs.cs b/win/C#/interop/MessageLoggedEventArgs.cs
new file mode 100644
index 000000000..a73b5ca0b
--- /dev/null
+++ b/win/C#/interop/MessageLoggedEventArgs.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public class MessageLoggedEventArgs : EventArgs
+ {
+ public string Message { get; set; }
+ }
+}
diff --git a/win/C#/interop/Model/Cropping.cs b/win/C#/interop/Model/Cropping.cs
new file mode 100644
index 000000000..1ba0e8ee1
--- /dev/null
+++ b/win/C#/interop/Model/Cropping.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public class Cropping
+ {
+ public int Top { get; set; }
+ public int Bottom { get; set; }
+ public int Left { get; set; }
+ public int Right { get; set; }
+ }
+}
diff --git a/win/C#/interop/Model/EncodeJob.cs b/win/C#/interop/Model/EncodeJob.cs
new file mode 100644
index 000000000..53058a921
--- /dev/null
+++ b/win/C#/interop/Model/EncodeJob.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace HandBrake.Interop
+{
+ public class EncodeJob
+ {
+ public SourceType SourceType { get; set; }
+ public string SourcePath { get; set; }
+
+ /// <summary>
+ /// Gets or sets the 1-based index of the title to encode.
+ /// </summary>
+ public int Title { get; set; }
+
+ /// <summary>
+ /// Gets or sets the angle to encode. 0 for default, 1+ for specified angle.
+ /// </summary>
+ public int Angle { get; set; }
+ public int ChapterStart { get; set; }
+ public int ChapterEnd { get; set; }
+
+ /// <summary>
+ /// Gets or sets the list of chosen audio tracks (1-based)
+ /// </summary>
+ public List<int> ChosenAudioTracks { get; set; }
+ public Subtitles Subtitles { get; set; }
+ public bool UseDefaultChapterNames { get; set; }
+ public List<string> CustomChapterNames { get; set; }
+
+ public string OutputPath { get; set; }
+
+ public EncodingProfile EncodingProfile { get; set; }
+
+ // The length of video to encode.
+ [XmlIgnore]
+ public TimeSpan Length { get; set; }
+
+ [XmlElement("Length")]
+ public string XmlLength
+ {
+ get { return this.Length.ToString(); }
+ set { this.Length = TimeSpan.Parse(value); }
+ }
+
+ public EncodeJob Clone()
+ {
+ EncodeJob clone = new EncodeJob
+ {
+ SourceType = this.SourceType,
+ SourcePath = this.SourcePath,
+ Title = this.Title,
+ ChapterStart = this.ChapterStart,
+ ChapterEnd = this.ChapterEnd,
+ ChosenAudioTracks = new List<int>(this.ChosenAudioTracks),
+ Subtitles = this.Subtitles,
+ UseDefaultChapterNames = this.UseDefaultChapterNames,
+ OutputPath = this.OutputPath,
+ EncodingProfile = this.EncodingProfile,
+ Length = this.Length
+ };
+
+ return clone;
+ }
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/Anamorphic.cs b/win/C#/interop/Model/Encoding/Anamorphic.cs
new file mode 100644
index 000000000..65a7f2352
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/Anamorphic.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public enum Anamorphic
+ {
+ [DisplayString("None")]
+ None = 0,
+ [DisplayString("Strict")]
+ Strict,
+ [DisplayString("Loose")]
+ Loose,
+ [DisplayString("Custom")]
+ Custom
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/AudioEncoder.cs b/win/C#/interop/Model/Encoding/AudioEncoder.cs
new file mode 100644
index 000000000..b4eee5249
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/AudioEncoder.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public enum AudioEncoder
+ {
+ [DisplayString("AAC (faac)")]
+ Faac = 0,
+
+ [DisplayString("MP3 (lame)")]
+ Lame,
+
+ [DisplayString("AC3 Passthrough")]
+ Ac3Passthrough,
+
+ [DisplayString("DTS Passthrough")]
+ DtsPassthrough,
+
+ [DisplayString("Vorbis (vorbis)")]
+ Vorbis
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/AudioEncoding.cs b/win/C#/interop/Model/Encoding/AudioEncoding.cs
new file mode 100644
index 000000000..8ff112c35
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/AudioEncoding.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public class AudioEncoding
+ {
+ public int InputNumber { get; set; }
+ public AudioEncoder Encoder { get; set; }
+ public int Bitrate { get; set; }
+ public Mixdown Mixdown { get; set; }
+ public string SampleRate { get; set; }
+ public double Drc { get; set; }
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/Decomb.cs b/win/C#/interop/Model/Encoding/Decomb.cs
new file mode 100644
index 000000000..9060b01eb
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/Decomb.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public enum Decomb
+ {
+ Off = 0,
+ Default,
+ Custom
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/Deinterlace.cs b/win/C#/interop/Model/Encoding/Deinterlace.cs
new file mode 100644
index 000000000..365f6003c
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/Deinterlace.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public enum Deinterlace
+ {
+ Off = 0,
+ Fast,
+ Slow,
+ Slower,
+ Custom
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/Denoise.cs b/win/C#/interop/Model/Encoding/Denoise.cs
new file mode 100644
index 000000000..146cbfd6f
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/Denoise.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public enum Denoise
+ {
+ Off = 0,
+ Weak,
+ Medium,
+ Strong,
+ Custom
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/Detelecine.cs b/win/C#/interop/Model/Encoding/Detelecine.cs
new file mode 100644
index 000000000..028abf44b
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/Detelecine.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public enum Detelecine
+ {
+ Off = 0,
+ Default,
+ Custom
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/EncodingProfile.cs b/win/C#/interop/Model/Encoding/EncodingProfile.cs
new file mode 100644
index 000000000..443abf477
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/EncodingProfile.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public class EncodingProfile
+ {
+ public EncodingProfile()
+ {
+ this.Cropping = new Cropping();
+ }
+
+ public OutputFormat OutputFormat { get; set; }
+ public OutputExtension PreferredExtension { get; set; }
+ public bool IncludeChapterMarkers { get; set; }
+ public bool LargeFile { get; set; }
+ public bool Optimize { get; set; }
+ public bool IPod5GSupport { get; set; }
+
+ public int Width { get; set; }
+ public int Height { get; set; }
+ public int MaxWidth { get; set; }
+ public int MaxHeight { get; set; }
+ public bool CustomCropping { get; set; }
+ public Cropping Cropping { get; set; }
+ public Anamorphic Anamorphic { get; set; }
+ public bool UseDisplayWidth { get; set; }
+ public int DisplayWidth { get; set; }
+ public bool KeepDisplayAspect { get; set; }
+ public int PixelAspectX { get; set; }
+ public int PixelAspectY { get; set; }
+ public int Modulus { get; set; }
+
+ public Deinterlace Deinterlace { get; set; }
+ public string CustomDeinterlace { get; set; }
+ public Decomb Decomb { get; set; }
+ public string CustomDecomb { get; set; }
+ public Detelecine Detelecine { get; set; }
+ public string CustomDetelecine { get; set; }
+ public Denoise Denoise { get; set; }
+ public string CustomDenoise { get; set; }
+ public int Deblock { get; set; }
+ public bool Grayscale { get; set; }
+
+ public VideoEncoder VideoEncoder { get; set; }
+ public string X264Options { get; set; }
+ public VideoEncodeRateType VideoEncodeRateType { get; set; }
+ public double Quality { get; set; }
+ public int TargetSize { get; set; }
+ public int VideoBitrate { get; set; }
+ public bool TwoPass { get; set; }
+ public bool TurboFirstPass { get; set; }
+ public double Framerate { get; set; }
+
+ public List<AudioEncoding> AudioEncodings { get; set; }
+
+ public EncodingProfile Clone()
+ {
+ EncodingProfile profile = new EncodingProfile
+ {
+ OutputFormat = this.OutputFormat,
+ PreferredExtension = this.PreferredExtension,
+ IncludeChapterMarkers = this.IncludeChapterMarkers,
+ LargeFile = this.LargeFile,
+ Optimize = this.Optimize,
+ IPod5GSupport = this.IPod5GSupport,
+
+ Width = this.Width,
+ Height = this.Height,
+ MaxWidth = this.MaxWidth,
+ MaxHeight = this.MaxHeight,
+ CustomCropping = this.CustomCropping,
+ Cropping = this.Cropping,
+ Anamorphic = this.Anamorphic,
+ UseDisplayWidth = this.UseDisplayWidth,
+ DisplayWidth = this.DisplayWidth,
+ KeepDisplayAspect = this.KeepDisplayAspect,
+ PixelAspectX = this.PixelAspectX,
+ PixelAspectY = this.PixelAspectY,
+ Modulus = this.Modulus,
+
+ Deinterlace = this.Deinterlace,
+ CustomDeinterlace = this.CustomDeinterlace,
+ Decomb = this.Decomb,
+ CustomDecomb = this.CustomDecomb,
+ Detelecine = this.Detelecine,
+ CustomDetelecine = this.CustomDetelecine,
+ Denoise = this.Denoise,
+ CustomDenoise = this.CustomDenoise,
+ Deblock = this.Deblock,
+ Grayscale = this.Grayscale,
+
+ VideoEncoder = this.VideoEncoder,
+ X264Options = this.X264Options,
+ VideoEncodeRateType = this.VideoEncodeRateType,
+ Quality = this.Quality,
+ TargetSize = this.TargetSize,
+ VideoBitrate = this.VideoBitrate,
+ TwoPass = this.TwoPass,
+ TurboFirstPass = this.TurboFirstPass,
+ Framerate = this.Framerate,
+
+ AudioEncodings = new List<AudioEncoding>(this.AudioEncodings)
+ };
+
+ return profile;
+ }
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/Mixdown.cs b/win/C#/interop/Model/Encoding/Mixdown.cs
new file mode 100644
index 000000000..2049d0921
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/Mixdown.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public enum Mixdown
+ {
+ [DisplayString("Dolby Pro Logic II")]
+ DolbyProLogicII = 0,
+
+ [DisplayString("Mono")]
+ Mono,
+
+ [DisplayString("Stereo")]
+ Stereo,
+
+ [DisplayString("Dolby Surround")]
+ DolbySurround,
+
+ [DisplayString("6 Channel Discrete")]
+ SixChannelDiscrete
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/OutputExtension.cs b/win/C#/interop/Model/Encoding/OutputExtension.cs
new file mode 100644
index 000000000..bcf709576
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/OutputExtension.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public enum OutputExtension
+ {
+ Mp4,
+ M4v
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/OutputFormat.cs b/win/C#/interop/Model/Encoding/OutputFormat.cs
new file mode 100644
index 000000000..52549e763
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/OutputFormat.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.ComponentModel;
+
+namespace HandBrake.Interop
+{
+ public enum OutputFormat
+ {
+ [DisplayString("MP4")]
+ Mp4,
+ [DisplayString("MKV")]
+ Mkv
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/VideoEncodeRateType.cs b/win/C#/interop/Model/Encoding/VideoEncodeRateType.cs
new file mode 100644
index 000000000..6c39e54d6
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/VideoEncodeRateType.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public enum VideoEncodeRateType
+ {
+ TargetSize = 0,
+ AverageBitrate,
+ ConstantQuality
+ }
+}
diff --git a/win/C#/interop/Model/Encoding/VideoEncoder.cs b/win/C#/interop/Model/Encoding/VideoEncoder.cs
new file mode 100644
index 000000000..912117b48
--- /dev/null
+++ b/win/C#/interop/Model/Encoding/VideoEncoder.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public enum VideoEncoder
+ {
+ [DisplayString("H.264 (x264)")]
+ X264 = 0,
+
+ [DisplayString("MPEG-4 (FFMpeg)")]
+ FFMpeg,
+
+ [DisplayString("VP3 (Theora)")]
+ Theora
+ }
+}
diff --git a/win/C#/interop/Model/Size.cs b/win/C#/interop/Model/Size.cs
new file mode 100644
index 000000000..f94cbd2fa
--- /dev/null
+++ b/win/C#/interop/Model/Size.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public class Size
+ {
+ public Size(int width, int height)
+ {
+ this.Width = width;
+ this.Height = height;
+ }
+
+ public int Width { get; set; }
+ public int Height { get; set; }
+ }
+}
diff --git a/win/C#/interop/Model/SourceSubtitle.cs b/win/C#/interop/Model/SourceSubtitle.cs
new file mode 100644
index 000000000..edfb68bf7
--- /dev/null
+++ b/win/C#/interop/Model/SourceSubtitle.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public class SourceSubtitle
+ {
+ /// <summary>
+ /// Gets or sets the 1-based subtitle track number. 0 means foriegn audio search.
+ /// </summary>
+ public int TrackNumber { get; set; }
+ public bool Default { get; set; }
+ public bool Forced { get; set; }
+ public bool BurnedIn { get; set; }
+
+ public SourceSubtitle Clone()
+ {
+ return new SourceSubtitle
+ {
+ TrackNumber = this.TrackNumber,
+ Default = this.Default,
+ Forced = this.Forced,
+ BurnedIn = this.BurnedIn
+ };
+ }
+ }
+}
diff --git a/win/C#/interop/Model/SourceType.cs b/win/C#/interop/Model/SourceType.cs
new file mode 100644
index 000000000..1a53aab32
--- /dev/null
+++ b/win/C#/interop/Model/SourceType.cs
@@ -0,0 +1,10 @@
+namespace HandBrake.Interop
+{
+ public enum SourceType
+ {
+ None = 0,
+ File,
+ VideoFolder,
+ Dvd
+ }
+} \ No newline at end of file
diff --git a/win/C#/interop/Model/SrtSubtitle.cs b/win/C#/interop/Model/SrtSubtitle.cs
new file mode 100644
index 000000000..199fe6ac6
--- /dev/null
+++ b/win/C#/interop/Model/SrtSubtitle.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public class SrtSubtitle
+ {
+ public bool Default { get; set; }
+ public string FileName { get; set; }
+ public string LanguageCode { get; set; }
+ public string CharacterCode { get; set; }
+ public int Offset { get; set; }
+
+ public SrtSubtitle Clone()
+ {
+ return new SrtSubtitle
+ {
+ Default = this.Default,
+ FileName = this.FileName,
+ LanguageCode = this.LanguageCode,
+ CharacterCode = this.CharacterCode,
+ Offset = this.Offset
+ };
+ }
+ }
+}
diff --git a/win/C#/interop/Model/Subtitles.cs b/win/C#/interop/Model/Subtitles.cs
new file mode 100644
index 000000000..1fab7354e
--- /dev/null
+++ b/win/C#/interop/Model/Subtitles.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public class Subtitles
+ {
+ public List<SrtSubtitle> SrtSubtitles { get; set; }
+ public List<SourceSubtitle> SourceSubtitles { get; set; }
+ }
+}
diff --git a/win/C#/interop/NativeList.cs b/win/C#/interop/NativeList.cs
new file mode 100644
index 000000000..c16c09950
--- /dev/null
+++ b/win/C#/interop/NativeList.cs
@@ -0,0 +1,34 @@
+namespace HandBrake.Interop
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ /// <summary>
+ /// Represents a HandBrake style native list.
+ /// </summary>
+ public class NativeList
+ {
+ /// <summary>
+ /// The list of native memory locations allocated for this list.
+ /// </summary>
+ private List<IntPtr> allocatedMemory = new List<IntPtr>();
+
+ /// <summary>
+ /// Gets or sets the pointer to the native list.
+ /// </summary>
+ public IntPtr ListPtr { get; set; }
+
+ /// <summary>
+ /// Gets the list of native memory locations allocated for this list.
+ /// </summary>
+ public List<IntPtr> AllocatedMemory
+ {
+ get
+ {
+ return allocatedMemory;
+ }
+ }
+ }
+}
diff --git a/win/C#/interop/Properties/AssemblyInfo.cs b/win/C#/interop/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..dcff50cc5
--- /dev/null
+++ b/win/C#/interop/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+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("HandBrakeInterop")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("HandBrakeInterop")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
+[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("cc59844b-9e1b-4854-8b92-3b24c646aee5")]
+
+// 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("1.3.0.0")]
+[assembly: AssemblyFileVersion("1.3.0.0")]
diff --git a/win/C#/interop/ScanProgressEventArgs.cs b/win/C#/interop/ScanProgressEventArgs.cs
new file mode 100644
index 000000000..f7e3a0f67
--- /dev/null
+++ b/win/C#/interop/ScanProgressEventArgs.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.Interop
+{
+ public class ScanProgressEventArgs : EventArgs
+ {
+ public int CurrentTitle { get; set; }
+ public int Titles { get; set; }
+ }
+}
diff --git a/win/C#/interop/SourceData/AudioTrack.cs b/win/C#/interop/SourceData/AudioTrack.cs
new file mode 100644
index 000000000..735ddd965
--- /dev/null
+++ b/win/C#/interop/SourceData/AudioTrack.cs
@@ -0,0 +1,80 @@
+/* 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. */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace HandBrake.SourceData
+{
+ /// <summary>
+ /// An object represending an AudioTrack associated with a Title, in a DVD
+ /// </summary>
+ public class AudioTrack
+ {
+ /// <summary>
+ /// The track number of this Audio Track
+ /// </summary>
+ public int TrackNumber { get; set; }
+
+ /// <summary>
+ /// The language (if detected) of this Audio Track
+ /// </summary>
+ public string Language { get; set; }
+
+ public string LanguageCode { get; set; }
+
+ public string Description { get; set; }
+
+ /// <summary>
+ /// The frequency (in MHz) of this Audio Track
+ /// </summary>
+ public int SampleRate { get; set; }
+
+ /// <summary>
+ /// The bitrate (in kbps) of this Audio Track
+ /// </summary>
+ public int Bitrate { get; set; }
+
+ public string Display
+ {
+ get
+ {
+ return this.GetDisplayString(true);
+ }
+ }
+
+ public string NoTrackDisplay
+ {
+ get
+ {
+ return this.GetDisplayString(false);
+ }
+ }
+
+ /// <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()
+ {
+ return this.GetDisplayString(true);
+ }
+
+ private string GetDisplayString(bool includeTrackNumber)
+ {
+ if (includeTrackNumber)
+ {
+ return this.TrackNumber + " " + this.Description;
+ }
+ else
+ {
+ return this.Description;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/win/C#/interop/SourceData/Chapter.cs b/win/C#/interop/SourceData/Chapter.cs
new file mode 100644
index 000000000..8e41282c4
--- /dev/null
+++ b/win/C#/interop/SourceData/Chapter.cs
@@ -0,0 +1,38 @@
+/* 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. */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace HandBrake.SourceData
+{
+ /// <summary>
+ /// An object representing a Chapter aosciated with a Title, in a DVD
+ /// </summary>
+ public class Chapter
+ {
+ /// <summary>
+ /// The number of this Chapter, in regards to its parent Title
+ /// </summary>
+ public int ChapterNumber { get; set; }
+
+ /// <summary>
+ /// The length in time this Chapter spans
+ /// </summary>
+ public TimeSpan Duration { get; set; }
+
+ /// <summary>
+ /// Override of the ToString method to make this object easier to use in the UI
+ /// </summary>
+ /// <returns>A string formatted as: {chapter #}</returns>
+ public override string ToString()
+ {
+ return this.ChapterNumber.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/win/C#/interop/SourceData/Subtitle.cs b/win/C#/interop/SourceData/Subtitle.cs
new file mode 100644
index 000000000..bf5d4e548
--- /dev/null
+++ b/win/C#/interop/SourceData/Subtitle.cs
@@ -0,0 +1,70 @@
+/* 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. */
+
+using System.Collections.Generic;
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace HandBrake.SourceData
+{
+ /// <summary>
+ /// An object that represents a subtitle associated with a Title, in a DVD
+ /// </summary>
+ public class Subtitle
+ {
+ /// <summary>
+ /// The track number of this Subtitle
+ /// </summary>
+ public int TrackNumber { get; set; }
+
+ /// <summary>
+ /// The language (if detected) of this Subtitle
+ /// </summary>
+ public string Language { get; set; }
+
+ /// <summary>
+ /// Langauage Code
+ /// </summary>
+ public string LanguageCode { get; set; }
+
+ public SubtitleType SubtitleType { get; set; }
+
+ /// <summary>
+ /// Subtitle Type
+ /// </summary>
+ public string TypeString
+ {
+ get
+ {
+ if (this.SubtitleType == SubtitleType.Picture)
+ {
+ return "Bitmap";
+ }
+ else
+ {
+ return "Text";
+ }
+ }
+ }
+
+ /// <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})", this.TrackNumber, this.Language, this.TypeString);
+ }
+
+ public string Display
+ {
+ get
+ {
+ return this.ToString();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/win/C#/interop/SourceData/SubtitleType.cs b/win/C#/interop/SourceData/SubtitleType.cs
new file mode 100644
index 000000000..68904fed4
--- /dev/null
+++ b/win/C#/interop/SourceData/SubtitleType.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HandBrake.SourceData
+{
+ public enum SubtitleType
+ {
+ Picture,
+ Text
+ }
+}
diff --git a/win/C#/interop/SourceData/Title.cs b/win/C#/interop/SourceData/Title.cs
new file mode 100644
index 000000000..8d69494ef
--- /dev/null
+++ b/win/C#/interop/SourceData/Title.cs
@@ -0,0 +1,115 @@
+/* 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. */
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text.RegularExpressions;
+using HandBrake.Interop;
+
+namespace HandBrake.SourceData
+{
+ /// <summary>
+ /// An object that represents a single Title of a DVD
+ /// </summary>
+ public class Title
+ {
+ private static readonly CultureInfo Culture = new CultureInfo("en-US", false);
+ private readonly List<AudioTrack> audioTracks;
+ private readonly List<Chapter> chapters;
+ private readonly List<Subtitle> subtitles;
+
+ /// <summary>
+ /// The constructor for this object
+ /// </summary>
+ public Title()
+ {
+ this.audioTracks = new List<AudioTrack>();
+ this.chapters = new List<Chapter>();
+ this.subtitles = new List<Subtitle>();
+ }
+
+ /// <summary>
+ /// Collection of chapters in this Title
+ /// </summary>
+ public List<Chapter> Chapters
+ {
+ get { return this.chapters; }
+ }
+
+ /// <summary>
+ /// Collection of audio tracks associated with this Title
+ /// </summary>
+ public List<AudioTrack> AudioTracks
+ {
+ get { return this.audioTracks; }
+ }
+
+ /// <summary>
+ /// Collection of subtitles associated with this Title
+ /// </summary>
+ public List<Subtitle> Subtitles
+ {
+ get { return this.subtitles; }
+ }
+
+ /// <summary>
+ /// The track number of this Title (1-based).
+ /// </summary>
+ public int TitleNumber { get; set; }
+
+ /// <summary>
+ /// The length in time of this Title
+ /// </summary>
+ public TimeSpan Duration { get; set; }
+
+ /// <summary>
+ /// The resolution (width/height) of this Title
+ /// </summary>
+ public Size Resolution { get; set; }
+
+ /// <summary>
+ /// The aspect ratio of this Title
+ /// </summary>
+ public double AspectRatio { get; set; }
+
+ public int AngleCount { get; set; }
+
+ /// <summary>
+ /// Par Value
+ /// </summary>
+ public Size ParVal { get; set; }
+
+ /// <summary>
+ /// The automatically detected crop region for this Title.
+ /// This is an int array with 4 items in it as so:
+ /// 0:
+ /// 1:
+ /// 2:
+ /// 3:
+ /// </summary>
+ public Cropping AutoCropDimensions { get; set; }
+
+ /// <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})", this.TitleNumber, this.Duration.Hours,
+ this.Duration.Minutes, this.Duration.Seconds);
+ }
+
+ public string Display
+ {
+ get
+ {
+ return this.ToString();
+ }
+ }
+ }
+} \ No newline at end of file