// 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 CollectPadsClipFunctionNative(IntPtr pads, IntPtr data, IntPtr inbuffer, out IntPtr outbuffer, IntPtr user_data);

	internal class CollectPadsClipFunctionInvoker {

		CollectPadsClipFunctionNative native_cb;
		IntPtr __data;
		GLib.DestroyNotify __notify;

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

		internal CollectPadsClipFunctionInvoker (CollectPadsClipFunctionNative native_cb) : this (native_cb, IntPtr.Zero, null) {}

		internal CollectPadsClipFunctionInvoker (CollectPadsClipFunctionNative native_cb, IntPtr data) : this (native_cb, data, null) {}

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

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

		Gst.FlowReturn InvokeNative (Gst.Base.CollectPads pads, Gst.Base.CollectData data, Gst.Buffer inbuffer, out Gst.Buffer outbuffer)
		{
			IntPtr native_data = GLib.Marshaller.StructureToPtrAlloc (data);
			inbuffer.Owned = false;
			IntPtr native_outbuffer;
			Gst.FlowReturn __result = (Gst.FlowReturn) native_cb (pads == null ? IntPtr.Zero : pads.Handle, native_data, inbuffer == null ? IntPtr.Zero : inbuffer.Handle, out native_outbuffer, __data);
			Marshal.FreeHGlobal (native_data);
			outbuffer = native_outbuffer == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (native_outbuffer, typeof (Gst.Buffer), true);
			return __result;
		}
	}

	internal class CollectPadsClipFunctionWrapper {

		public int NativeCallback (IntPtr pads, IntPtr data, IntPtr inbuffer, out IntPtr outbuffer, IntPtr user_data)
		{
			try {
				Gst.Buffer myoutbuffer;

				Gst.FlowReturn __ret = managed (GLib.Object.GetObject(pads) as Gst.Base.CollectPads, Gst.Base.CollectData.New (data), inbuffer == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (inbuffer, typeof (Gst.Buffer), true), out myoutbuffer);
				outbuffer = myoutbuffer == null ? IntPtr.Zero : myoutbuffer.Handle;

				if (release_on_call)
					gch.Free ();
				return (int) __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 CollectPadsClipFunctionNative NativeDelegate;
		Gst.Base.CollectPadsClipFunction managed;

		public CollectPadsClipFunctionWrapper (Gst.Base.CollectPadsClipFunction managed)
		{
			this.managed = managed;
			if (managed != null)
				NativeDelegate = new CollectPadsClipFunctionNative (NativeCallback);
		}

		public static Gst.Base.CollectPadsClipFunction GetManagedDelegate (CollectPadsClipFunctionNative native)
		{
			if (native == null)
				return null;
			CollectPadsClipFunctionWrapper wrapper = (CollectPadsClipFunctionWrapper) native.Target;
			if (wrapper == null)
				return null;
			return wrapper.managed;
		}
	}
#endregion
}
