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

namespace Gst.AudioSharp {

	using System;
	using System.Runtime.InteropServices;

#region Autogenerated code
	[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
	internal delegate void AudioBaseSinkCustomSlavingCallbackNative(IntPtr sink, ulong etime, ulong itime, long requested_skew, int discont_reason, IntPtr user_data);

	internal class AudioBaseSinkCustomSlavingCallbackInvoker {

		AudioBaseSinkCustomSlavingCallbackNative native_cb;
		IntPtr __data;
		GLib.DestroyNotify __notify;

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

		internal AudioBaseSinkCustomSlavingCallbackInvoker (AudioBaseSinkCustomSlavingCallbackNative native_cb) : this (native_cb, IntPtr.Zero, null) {}

		internal AudioBaseSinkCustomSlavingCallbackInvoker (AudioBaseSinkCustomSlavingCallbackNative native_cb, IntPtr data) : this (native_cb, data, null) {}

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

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

		void InvokeNative (Gst.Audio.AudioBaseSink sink, ulong etime, ulong itime, long requested_skew, Gst.Audio.AudioBaseSinkDiscontReason discont_reason)
		{
			native_cb (sink == null ? IntPtr.Zero : sink.Handle, etime, itime, requested_skew, (int) discont_reason, __data);
		}
	}

	internal class AudioBaseSinkCustomSlavingCallbackWrapper {

		public void NativeCallback (IntPtr sink, ulong etime, ulong itime, long requested_skew, int discont_reason, IntPtr user_data)
		{
			try {
				managed (GLib.Object.GetObject(sink) as Gst.Audio.AudioBaseSink, etime, itime, requested_skew, (Gst.Audio.AudioBaseSinkDiscontReason) discont_reason);
				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 AudioBaseSinkCustomSlavingCallbackNative NativeDelegate;
		Gst.Audio.AudioBaseSinkCustomSlavingCallback managed;

		public AudioBaseSinkCustomSlavingCallbackWrapper (Gst.Audio.AudioBaseSinkCustomSlavingCallback managed)
		{
			this.managed = managed;
			if (managed != null)
				NativeDelegate = new AudioBaseSinkCustomSlavingCallbackNative (NativeCallback);
		}

		public static Gst.Audio.AudioBaseSinkCustomSlavingCallback GetManagedDelegate (AudioBaseSinkCustomSlavingCallbackNative native)
		{
			if (native == null)
				return null;
			AudioBaseSinkCustomSlavingCallbackWrapper wrapper = (AudioBaseSinkCustomSlavingCallbackWrapper) native.Target;
			if (wrapper == null)
				return null;
			return wrapper.managed;
		}
	}
#endregion
}
