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

namespace GstSharp {

	using System;
	using System.Runtime.InteropServices;

#region Autogenerated code
	[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
	internal delegate bool PluginInitFuncNative(IntPtr plugin);

	internal class PluginInitFuncInvoker {

		PluginInitFuncNative native_cb;
		IntPtr __data;
		GLib.DestroyNotify __notify;

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

		internal PluginInitFuncInvoker (PluginInitFuncNative native_cb) : this (native_cb, IntPtr.Zero, null) {}

		internal PluginInitFuncInvoker (PluginInitFuncNative native_cb, IntPtr data) : this (native_cb, data, null) {}

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

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

		bool InvokeNative (Gst.Plugin plugin)
		{
			bool __result = native_cb (plugin == null ? IntPtr.Zero : plugin.Handle);
			return __result;
		}
	}

	internal class PluginInitFuncWrapper {

		public bool NativeCallback (IntPtr plugin)
		{
			try {
				bool __ret = managed (GLib.Object.GetObject(plugin) as Gst.Plugin);
				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 PluginInitFuncNative NativeDelegate;
		Gst.PluginInitFunc managed;

		public PluginInitFuncWrapper (Gst.PluginInitFunc managed)
		{
			this.managed = managed;
			if (managed != null)
				NativeDelegate = new PluginInitFuncNative (NativeCallback);
		}

		public static Gst.PluginInitFunc GetManagedDelegate (PluginInitFuncNative native)
		{
			if (native == null)
				return null;
			PluginInitFuncWrapper wrapper = (PluginInitFuncWrapper) native.Target;
			if (wrapper == null)
				return null;
			return wrapper.managed;
		}
	}
#endregion
}
