// 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 bool CollectPadsEventFunctionNative(IntPtr pads, IntPtr pad, IntPtr evnt, IntPtr user_data);

	internal class CollectPadsEventFunctionInvoker {

		CollectPadsEventFunctionNative native_cb;
		IntPtr __data;
		GLib.DestroyNotify __notify;

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

		internal CollectPadsEventFunctionInvoker (CollectPadsEventFunctionNative native_cb) : this (native_cb, IntPtr.Zero, null) {}

		internal CollectPadsEventFunctionInvoker (CollectPadsEventFunctionNative native_cb, IntPtr data) : this (native_cb, data, null) {}

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

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

		bool InvokeNative (Gst.Base.CollectPads pads, Gst.Base.CollectData pad, Gst.Event evnt)
		{
			IntPtr native_pad = GLib.Marshaller.StructureToPtrAlloc (pad);
			bool __result = native_cb (pads == null ? IntPtr.Zero : pads.Handle, native_pad, evnt == null ? IntPtr.Zero : evnt.Handle, __data);
			Marshal.FreeHGlobal (native_pad);
			return __result;
		}
	}

	internal class CollectPadsEventFunctionWrapper {

		public bool NativeCallback (IntPtr pads, IntPtr pad, IntPtr evnt, IntPtr user_data)
		{
			try {
				bool __ret = managed (GLib.Object.GetObject(pads) as Gst.Base.CollectPads, Gst.Base.CollectData.New (pad), evnt == IntPtr.Zero ? null : (Gst.Event) GLib.Opaque.GetOpaque (evnt, typeof (Gst.Event), false));
				if (release_on_call)
					gch.Free ();
				return __ret;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, false);
				return false;
			}
		}

		bool release_on_call = false;
		GCHandle gch;

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

		internal CollectPadsEventFunctionNative NativeDelegate;
		Gst.Base.CollectPadsEventFunction managed;

		public CollectPadsEventFunctionWrapper (Gst.Base.CollectPadsEventFunction managed)
		{
			this.managed = managed;
			if (managed != null)
				NativeDelegate = new CollectPadsEventFunctionNative (NativeCallback);
		}

		public static Gst.Base.CollectPadsEventFunction GetManagedDelegate (CollectPadsEventFunctionNative native)
		{
			if (native == null)
				return null;
			CollectPadsEventFunctionWrapper wrapper = (CollectPadsEventFunctionWrapper) native.Target;
			if (wrapper == null)
				return null;
			return wrapper.managed;
		}
	}
#endregion
}
