// --------------------------------------------------------------------------------------------------------------------
//
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
//
//
// Helper utilities for native interop.
//
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrake.Interop
{
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using HandBrake.Interop.HbLib;
///
/// Helper utilities for native interop.
///
public static class InteropUtilities
{
///
/// Reads the given native structure pointer.
///
/// The type to convert the structure to.
/// The pointer to the native structure.
/// The converted structure.
public static T ReadStructure(IntPtr structPtr)
{
return (T)Marshal.PtrToStructure(structPtr, typeof(T));
}
///
/// Converts the given native HandBrake list to a managed list.
///
/// The type of structure in the list.
/// The pointer to the native list.
/// The converted managed list.
public static List ToList(this IntPtr listPtr)
{
List returnList = new List();
hb_list_s itemList = ReadStructure(listPtr);
for (int i = 0; i < itemList.items_count; i++)
{
IntPtr itemPtr = Marshal.ReadIntPtr(itemList.items, i * Marshal.SizeOf(typeof(IntPtr)));
returnList.Add(ReadStructure(itemPtr));
}
return returnList;
}
///
/// Converts the HB list to a managed list of pointers.
///
/// The list to convert.
/// The managed list of pointers.
public static List ToIntPtrList(this IntPtr listPtr)
{
var returnList = new List();
hb_list_s itemList = ReadStructure(listPtr);
for (int i = 0; i < itemList.items_count; i++)
{
IntPtr itemPtr = Marshal.ReadIntPtr(itemList.items, i * Marshal.SizeOf(typeof(IntPtr)));
returnList.Add(itemPtr);
}
return returnList;
}
///
/// Converts the given native array to a managed collection.
///
/// The type of item in the list.
/// The pointer to the array.
/// The number of items in the array.
/// The converted collection.
public static IEnumerable ConvertArray(IntPtr arrayPtr, int count)
{
IntPtr currentItem = arrayPtr;
var result = new List();
for (int i = 0; i < count; i++)
{
T nativeEncoder = ReadStructure(currentItem);
result.Add(nativeEncoder);
currentItem = IntPtr.Add(currentItem, Marshal.SizeOf(typeof(T)));
}
return result;
}
///
/// Creats a new, empty native HandBrake list.
///
/// The capacity of the new list.
/// The new native list.
public static NativeList CreateNativeList(int capacity)
{
NativeList returnList = new NativeList();
int intSize = Marshal.SizeOf(typeof(IntPtr));
IntPtr nativeListInternal = Marshal.AllocHGlobal(capacity * intSize);
returnList.AllocatedMemory.Add(nativeListInternal);
hb_list_s nativeListStruct = new hb_list_s();
nativeListStruct.items = nativeListInternal;
nativeListStruct.items_alloc = capacity;
nativeListStruct.items_count = 0;
IntPtr nativeListStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_list_s)));
Marshal.StructureToPtr(nativeListStruct, nativeListStructPtr, false);
returnList.ListPtr = nativeListStructPtr;
return returnList;
}
///
/// Creates a native HandBrake list from the given managed list of pointers.
///
/// The managed list to convert.
/// The converted native list.
public static NativeList CreateIntPtrList(List 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;
}
///
/// Creates a native HandBrake list from the given managed list of structures.
///
/// The type of structures in the list.
/// The managed list to convert.
/// The converted native list.
public static NativeList ConvertListBack(List 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;
}
///
/// Closes the given job.
///
/// The pointer to the job.
public static void CloseJob(IntPtr nativeJobPtr)
{
// Create a point to the job pointer first.
IntPtr nativeJobPtrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
// Assign the new pointer to the job pointer and tell HB to clean the job up.
Marshal.WriteIntPtr(nativeJobPtrPtr, nativeJobPtr);
HBFunctions.hb_job_close(nativeJobPtrPtr);
// Free the pointer we used.
Marshal.FreeHGlobal(nativeJobPtrPtr);
}
///
/// Frees all the memory locations in the given list.
///
/// The list of memory locations to free.
public static void FreeMemory(List memoryList)
{
foreach (IntPtr memoryLocation in memoryList)
{
Marshal.FreeHGlobal(memoryLocation);
}
}
}
}