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

namespace Gst.RtspServerSharp {

	using System;
	using System.Runtime.InteropServices;

#region Autogenerated code
	[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
	internal delegate bool RTSPClientSendFuncNative(IntPtr client, IntPtr message, bool close, IntPtr user_data);

	internal class RTSPClientSendFuncInvoker {

		RTSPClientSendFuncNative native_cb;
		IntPtr __data;
		GLib.DestroyNotify __notify;

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

		internal RTSPClientSendFuncInvoker (RTSPClientSendFuncNative native_cb) : this (native_cb, IntPtr.Zero, null) {}

		internal RTSPClientSendFuncInvoker (RTSPClientSendFuncNative native_cb, IntPtr data) : this (native_cb, data, null) {}

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

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

		bool InvokeNative (Gst.RtspServer.RTSPClient client, Gst.Rtsp.RTSPMessage message, bool close)
		{
			IntPtr native_message = GLib.Marshaller.StructureToPtrAlloc (message);
			bool __result = native_cb (client == null ? IntPtr.Zero : client.Handle, native_message, close, __data);
			Marshal.FreeHGlobal (native_message);
			return __result;
		}
	}

	internal class RTSPClientSendFuncWrapper {

		public bool NativeCallback (IntPtr client, IntPtr message, bool close, IntPtr user_data)
		{
			try {
				bool __ret = managed (GLib.Object.GetObject(client) as Gst.RtspServer.RTSPClient, Gst.Rtsp.RTSPMessage.New (message), close);
				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 RTSPClientSendFuncNative NativeDelegate;
		Gst.RtspServer.RTSPClientSendFunc managed;

		public RTSPClientSendFuncWrapper (Gst.RtspServer.RTSPClientSendFunc managed)
		{
			this.managed = managed;
			if (managed != null)
				NativeDelegate = new RTSPClientSendFuncNative (NativeCallback);
		}

		public static Gst.RtspServer.RTSPClientSendFunc GetManagedDelegate (RTSPClientSendFuncNative native)
		{
			if (native == null)
				return null;
			RTSPClientSendFuncWrapper wrapper = (RTSPClientSendFuncWrapper) native.Target;
			if (wrapper == null)
				return null;
			return wrapper.managed;
		}
	}
#endregion
}
