// This file was generated by the Gtk# code generator.
// Any changes made will be lost if regenerated.

namespace Gst.BaseSharp {

	using System;
	using System.Runtime.InteropServices;

#region Autogenerated code
	[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
	internal delegate int CollectPadsCompareFunctionNative(IntPtr pads, IntPtr data1, ulong timestamp1, IntPtr data2, ulong timestamp2, IntPtr user_data);

	internal class CollectPadsCompareFunctionInvoker {

		CollectPadsCompareFunctionNative native_cb;
		IntPtr __data;
		GLib.DestroyNotify __notify;

		~CollectPadsCompareFunctionInvoker ()
		{
			if (__notify == null)
				return;
			__notify (__data);
		}

		internal CollectPadsCompareFunctionInvoker (CollectPadsCompareFunctionNative native_cb) : this (native_cb, IntPtr.Zero, null) {}

		internal CollectPadsCompareFunctionInvoker (CollectPadsCompareFunctionNative native_cb, IntPtr data) : this (native_cb, data, null) {}

		internal CollectPadsCompareFunctionInvoker (CollectPadsCompareFunctionNative native_cb, IntPtr data, GLib.DestroyNotify notify)
		{
			this.native_cb = native_cb;
			__data = data;
			__notify = notify;
		}

		internal Gst.Base.CollectPadsCompareFunction Handler {
			get {
				return new Gst.Base.CollectPadsCompareFunction(InvokeNative);
			}
		}

		int InvokeNative (Gst.Base.CollectPads pads, Gst.Base.CollectData data1, ulong timestamp1, Gst.Base.CollectData data2, ulong timestamp2)
		{
			IntPtr native_data1 = GLib.Marshaller.StructureToPtrAlloc (data1);
			IntPtr native_data2 = GLib.Marshaller.StructureToPtrAlloc (data2);
			int __result = native_cb (pads == null ? IntPtr.Zero : pads.Handle, native_data1, timestamp1, native_data2, timestamp2, __data);
			Marshal.FreeHGlobal (native_data1);
			Marshal.FreeHGlobal (native_data2);
			return __result;
		}
	}

	internal class CollectPadsCompareFunctionWrapper {

		public int NativeCallback (IntPtr pads, IntPtr data1, ulong timestamp1, IntPtr data2, ulong timestamp2, IntPtr user_data)
		{
			try {
				int __ret = managed (GLib.Object.GetObject(pads) as Gst.Base.CollectPads, Gst.Base.CollectData.New (data1), timestamp1, Gst.Base.CollectData.New (data2), timestamp2);
				if (release_on_call)
					gch.Free ();
				return __ret;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: Above call does not return.
				throw e;
			}
		}

		bool release_on_call = false;
		GCHandle gch;

		public void PersistUntilCalled ()
		{
			release_on_call = true;
			gch = GCHandle.Alloc (this);
		}

		internal CollectPadsCompareFunctionNative NativeDelegate;
		Gst.Base.CollectPadsCompareFunction managed;

		public CollectPadsCompareFunctionWrapper (Gst.Base.CollectPadsCompareFunction managed)
		{
			this.managed = managed;
			if (managed != null)
				NativeDelegate = new CollectPadsCompareFunctionNative (NativeCallback);
		}

		public static Gst.Base.CollectPadsCompareFunction GetManagedDelegate (CollectPadsCompareFunctionNative native)
		{
			if (native == null)
				return null;
			CollectPadsCompareFunctionWrapper wrapper = (CollectPadsCompareFunctionWrapper) native.Target;
			if (wrapper == null)
				return null;
			return wrapper.managed;
		}
	}
#endregion
}
