// 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 CollectPadsQueryFunctionNative(IntPtr pads, IntPtr pad, IntPtr query, IntPtr user_data);

	internal class CollectPadsQueryFunctionInvoker {

		CollectPadsQueryFunctionNative native_cb;
		IntPtr __data;
		GLib.DestroyNotify __notify;

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

		internal CollectPadsQueryFunctionInvoker (CollectPadsQueryFunctionNative native_cb) : this (native_cb, IntPtr.Zero, null) {}

		internal CollectPadsQueryFunctionInvoker (CollectPadsQueryFunctionNative native_cb, IntPtr data) : this (native_cb, data, null) {}

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

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

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

	internal class CollectPadsQueryFunctionWrapper {

		public bool NativeCallback (IntPtr pads, IntPtr pad, IntPtr query, IntPtr user_data)
		{
			try {
				bool __ret = managed (GLib.Object.GetObject(pads) as Gst.Base.CollectPads, Gst.Base.CollectData.New (pad), query == IntPtr.Zero ? null : (Gst.Query) GLib.Opaque.GetOpaque (query, typeof (Gst.Query), 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 CollectPadsQueryFunctionNative NativeDelegate;
		Gst.Base.CollectPadsQueryFunction managed;

		public CollectPadsQueryFunctionWrapper (Gst.Base.CollectPadsQueryFunction managed)
		{
			this.managed = managed;
			if (managed != null)
				NativeDelegate = new CollectPadsQueryFunctionNative (NativeCallback);
		}

		public static Gst.Base.CollectPadsQueryFunction GetManagedDelegate (CollectPadsQueryFunctionNative native)
		{
			if (native == null)
				return null;
			CollectPadsQueryFunctionWrapper wrapper = (CollectPadsQueryFunctionWrapper) native.Target;
			if (wrapper == null)
				return null;
			return wrapper.managed;
		}
	}
#endregion
}
