// 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 void DataQueueEmptyCallbackNative(IntPtr queue, IntPtr checkdata);

	internal class DataQueueEmptyCallbackInvoker {

		DataQueueEmptyCallbackNative native_cb;
		IntPtr __data;
		GLib.DestroyNotify __notify;

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

		internal DataQueueEmptyCallbackInvoker (DataQueueEmptyCallbackNative native_cb) : this (native_cb, IntPtr.Zero, null) {}

		internal DataQueueEmptyCallbackInvoker (DataQueueEmptyCallbackNative native_cb, IntPtr data) : this (native_cb, data, null) {}

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

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

		void InvokeNative (Gst.Base.DataQueue queue, IntPtr checkdata)
		{
			native_cb (queue == null ? IntPtr.Zero : queue.Handle, __data);
		}
	}

	internal class DataQueueEmptyCallbackWrapper {

		public void NativeCallback (IntPtr queue, IntPtr checkdata)
		{
			try {
				managed (GLib.Object.GetObject(queue) as Gst.Base.DataQueue, checkdata);
				if (release_on_call)
					gch.Free ();
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, false);
			}
		}

		bool release_on_call = false;
		GCHandle gch;

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

		internal DataQueueEmptyCallbackNative NativeDelegate;
		Gst.Base.DataQueueEmptyCallback managed;

		public DataQueueEmptyCallbackWrapper (Gst.Base.DataQueueEmptyCallback managed)
		{
			this.managed = managed;
			if (managed != null)
				NativeDelegate = new DataQueueEmptyCallbackNative (NativeCallback);
		}

		public static Gst.Base.DataQueueEmptyCallback GetManagedDelegate (DataQueueEmptyCallbackNative native)
		{
			if (native == null)
				return null;
			DataQueueEmptyCallbackWrapper wrapper = (DataQueueEmptyCallbackWrapper) native.Target;
			if (wrapper == null)
				return null;
			return wrapper.managed;
		}
	}
#endregion
}
