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

namespace Gst.Audio {

	using System;
	using System.Collections;
	using System.Collections.Generic;
	using System.Runtime.InteropServices;

#region Autogenerated code
	public partial class AudioDecoder : Gst.Element {

		protected AudioDecoder (IntPtr raw) : base(raw) {}

		protected AudioDecoder() : base(IntPtr.Zero)
		{
			CreateNativeObject (new string [0], new GLib.Value [0]);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern int gst_audio_decoder_get_max_errors(IntPtr raw);

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_max_errors(IntPtr raw, int num);

		[GLib.Property ("max-errors")]
		public int MaxErrors {
			get  {
				int raw_ret = gst_audio_decoder_get_max_errors(Handle);
				int ret = raw_ret;
				return ret;
			}
			set  {
				gst_audio_decoder_set_max_errors(Handle, value);
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern ulong gst_audio_decoder_get_min_latency(IntPtr raw);

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_min_latency(IntPtr raw, ulong num);

		[GLib.Property ("min-latency")]
		public ulong MinLatency {
			get  {
				ulong raw_ret = gst_audio_decoder_get_min_latency(Handle);
				ulong ret = raw_ret;
				return ret;
			}
			set  {
				gst_audio_decoder_set_min_latency(Handle, value);
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_audio_decoder_get_plc(IntPtr raw);

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_plc(IntPtr raw, bool enabled);

		[GLib.Property ("plc")]
		public bool Plc {
			get  {
				bool raw_ret = gst_audio_decoder_get_plc(Handle);
				bool ret = raw_ret;
				return ret;
			}
			set  {
				gst_audio_decoder_set_plc(Handle, value);
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern ulong gst_audio_decoder_get_tolerance(IntPtr raw);

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_tolerance(IntPtr raw, ulong tolerance);

		[GLib.Property ("tolerance")]
		public ulong Tolerance {
			get  {
				ulong raw_ret = gst_audio_decoder_get_tolerance(Handle);
				ulong ret = raw_ret;
				return ret;
			}
			set  {
				gst_audio_decoder_set_tolerance(Handle, value);
			}
		}

		public Gst.Pad Sinkpad {
			get {
				unsafe {
					IntPtr* raw_ptr = (IntPtr*)(((byte*)Handle) + abi_info.GetFieldOffset("sinkpad"));
					return GLib.Object.GetObject((*raw_ptr)) as Gst.Pad;
				}
			}
		}

		public Gst.Pad Srcpad {
			get {
				unsafe {
					IntPtr* raw_ptr = (IntPtr*)(((byte*)Handle) + abi_info.GetFieldOffset("srcpad"));
					return GLib.Object.GetObject((*raw_ptr)) as Gst.Pad;
				}
			}
		}

		public GLib.RecMutex StreamLock {
			get {
				unsafe {
					IntPtr* raw_ptr = (IntPtr*)(((byte*)Handle) + abi_info.GetFieldOffset("stream_lock"));
					return new GLib.RecMutex((*raw_ptr));
				}
			}
		}

		public Gst.Segment InputSegment {
			get {
				unsafe {
					IntPtr* raw_ptr = (IntPtr*)(((byte*)Handle) + abi_info.GetFieldOffset("input_segment"));
					return Gst.Segment.New ((*raw_ptr));
				}
			}
		}

		public Gst.Segment OutputSegment {
			get {
				unsafe {
					IntPtr* raw_ptr = (IntPtr*)(((byte*)Handle) + abi_info.GetFieldOffset("output_segment"));
					return Gst.Segment.New ((*raw_ptr));
				}
			}
		}

		static StartNativeDelegate Start_cb_delegate;
		static StartNativeDelegate StartVMCallback {
			get {
				if (Start_cb_delegate == null)
					Start_cb_delegate = new StartNativeDelegate (Start_cb);
				return Start_cb_delegate;
			}
		}

		static void OverrideStart (GLib.GType gtype)
		{
			OverrideStart (gtype, StartVMCallback);
		}

		static void OverrideStart (GLib.GType gtype, StartNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("start"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool StartNativeDelegate (IntPtr inst);

		static bool Start_cb (IntPtr inst)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnStart ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideStart")]
		protected virtual bool OnStart ()
		{
			return InternalStart ();
		}

		private bool InternalStart ()
		{
			StartNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("start"));
				unmanaged = (StartNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(StartNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static StopNativeDelegate Stop_cb_delegate;
		static StopNativeDelegate StopVMCallback {
			get {
				if (Stop_cb_delegate == null)
					Stop_cb_delegate = new StopNativeDelegate (Stop_cb);
				return Stop_cb_delegate;
			}
		}

		static void OverrideStop (GLib.GType gtype)
		{
			OverrideStop (gtype, StopVMCallback);
		}

		static void OverrideStop (GLib.GType gtype, StopNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("stop"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool StopNativeDelegate (IntPtr inst);

		static bool Stop_cb (IntPtr inst)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnStop ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideStop")]
		protected virtual bool OnStop ()
		{
			return InternalStop ();
		}

		private bool InternalStop ()
		{
			StopNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("stop"));
				unmanaged = (StopNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(StopNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static SetFormatNativeDelegate SetFormat_cb_delegate;
		static SetFormatNativeDelegate SetFormatVMCallback {
			get {
				if (SetFormat_cb_delegate == null)
					SetFormat_cb_delegate = new SetFormatNativeDelegate (SetFormat_cb);
				return SetFormat_cb_delegate;
			}
		}

		static void OverrideSetFormat (GLib.GType gtype)
		{
			OverrideSetFormat (gtype, SetFormatVMCallback);
		}

		static void OverrideSetFormat (GLib.GType gtype, SetFormatNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("set_format"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool SetFormatNativeDelegate (IntPtr inst, IntPtr caps);

		static bool SetFormat_cb (IntPtr inst, IntPtr caps)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnSetFormat (caps == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (caps, typeof (Gst.Caps), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideSetFormat")]
		protected virtual bool OnSetFormat (Gst.Caps caps)
		{
			return InternalSetFormat (caps);
		}

		private bool InternalSetFormat (Gst.Caps caps)
		{
			SetFormatNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("set_format"));
				unmanaged = (SetFormatNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(SetFormatNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, caps == null ? IntPtr.Zero : caps.Handle);
			return __result;
		}

		static ParseNativeDelegate Parse_cb_delegate;
		static ParseNativeDelegate ParseVMCallback {
			get {
				if (Parse_cb_delegate == null)
					Parse_cb_delegate = new ParseNativeDelegate (Parse_cb);
				return Parse_cb_delegate;
			}
		}

		static void OverrideParse (GLib.GType gtype)
		{
			OverrideParse (gtype, ParseVMCallback);
		}

		static void OverrideParse (GLib.GType gtype, ParseNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("parse"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate int ParseNativeDelegate (IntPtr inst, IntPtr adapter, out int offset, out int length);

		static int Parse_cb (IntPtr inst, IntPtr adapter, out int offset, out int length)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				Gst.FlowReturn __result;
				__result = __obj.OnParse (GLib.Object.GetObject(adapter) as Gst.Base.Adapter, out offset, out length);
				return (int) __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideParse")]
		protected virtual Gst.FlowReturn OnParse (Gst.Base.Adapter adapter, out int offset, out int length)
		{
			return InternalParse (adapter, out offset, out length);
		}

		private Gst.FlowReturn InternalParse (Gst.Base.Adapter adapter, out int offset, out int length)
		{
			ParseNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("parse"));
				unmanaged = (ParseNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(ParseNativeDelegate));
			}
			if (unmanaged == null) throw new InvalidOperationException ("No base method to invoke");

			int __result = unmanaged (this.Handle, adapter == null ? IntPtr.Zero : adapter.Handle, out offset, out length);
			return (Gst.FlowReturn) __result;
		}

		static HandleFrameNativeDelegate HandleFrame_cb_delegate;
		static HandleFrameNativeDelegate HandleFrameVMCallback {
			get {
				if (HandleFrame_cb_delegate == null)
					HandleFrame_cb_delegate = new HandleFrameNativeDelegate (HandleFrame_cb);
				return HandleFrame_cb_delegate;
			}
		}

		static void OverrideHandleFrame (GLib.GType gtype)
		{
			OverrideHandleFrame (gtype, HandleFrameVMCallback);
		}

		static void OverrideHandleFrame (GLib.GType gtype, HandleFrameNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("handle_frame"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate int HandleFrameNativeDelegate (IntPtr inst, IntPtr buffer);

		static int HandleFrame_cb (IntPtr inst, IntPtr buffer)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				Gst.FlowReturn __result;
				__result = __obj.OnHandleFrame (buffer == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (buffer, typeof (Gst.Buffer), false));
				return (int) __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideHandleFrame")]
		protected virtual Gst.FlowReturn OnHandleFrame (Gst.Buffer buffer)
		{
			return InternalHandleFrame (buffer);
		}

		private Gst.FlowReturn InternalHandleFrame (Gst.Buffer buffer)
		{
			HandleFrameNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("handle_frame"));
				unmanaged = (HandleFrameNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(HandleFrameNativeDelegate));
			}
			if (unmanaged == null) return (Gst.FlowReturn) 0;

			int __result = unmanaged (this.Handle, buffer == null ? IntPtr.Zero : buffer.Handle);
			return (Gst.FlowReturn) __result;
		}

		static FlushNativeDelegate Flush_cb_delegate;
		static FlushNativeDelegate FlushVMCallback {
			get {
				if (Flush_cb_delegate == null)
					Flush_cb_delegate = new FlushNativeDelegate (Flush_cb);
				return Flush_cb_delegate;
			}
		}

		static void OverrideFlush (GLib.GType gtype)
		{
			OverrideFlush (gtype, FlushVMCallback);
		}

		static void OverrideFlush (GLib.GType gtype, FlushNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("flush"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate void FlushNativeDelegate (IntPtr inst, bool hard);

		static void Flush_cb (IntPtr inst, bool hard)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				__obj.OnFlush (hard);
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, false);
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideFlush")]
		protected virtual void OnFlush (bool hard)
		{
			InternalFlush (hard);
		}

		private void InternalFlush (bool hard)
		{
			FlushNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("flush"));
				unmanaged = (FlushNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(FlushNativeDelegate));
			}
			if (unmanaged == null) return;

			unmanaged (this.Handle, hard);
		}

		static PrePushNativeDelegate PrePush_cb_delegate;
		static PrePushNativeDelegate PrePushVMCallback {
			get {
				if (PrePush_cb_delegate == null)
					PrePush_cb_delegate = new PrePushNativeDelegate (PrePush_cb);
				return PrePush_cb_delegate;
			}
		}

		static void OverridePrePush (GLib.GType gtype)
		{
			OverridePrePush (gtype, PrePushVMCallback);
		}

		static void OverridePrePush (GLib.GType gtype, PrePushNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("pre_push"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate int PrePushNativeDelegate (IntPtr inst, IntPtr buffer);

		static int PrePush_cb (IntPtr inst, IntPtr buffer)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				Gst.FlowReturn __result;
				__result = __obj.OnPrePush (buffer == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (buffer, typeof (Gst.Buffer), false));
				return (int) __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverridePrePush")]
		protected virtual Gst.FlowReturn OnPrePush (Gst.Buffer buffer)
		{
			return InternalPrePush (buffer);
		}

		private Gst.FlowReturn InternalPrePush (Gst.Buffer buffer)
		{
			PrePushNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("pre_push"));
				unmanaged = (PrePushNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(PrePushNativeDelegate));
			}
			if (unmanaged == null) return (Gst.FlowReturn) 0;

			int __result = unmanaged (this.Handle, buffer == null ? IntPtr.Zero : buffer.Handle);
			return (Gst.FlowReturn) __result;
		}

		static SinkEventNativeDelegate SinkEvent_cb_delegate;
		static SinkEventNativeDelegate SinkEventVMCallback {
			get {
				if (SinkEvent_cb_delegate == null)
					SinkEvent_cb_delegate = new SinkEventNativeDelegate (SinkEvent_cb);
				return SinkEvent_cb_delegate;
			}
		}

		static void OverrideSinkEvent (GLib.GType gtype)
		{
			OverrideSinkEvent (gtype, SinkEventVMCallback);
		}

		static void OverrideSinkEvent (GLib.GType gtype, SinkEventNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("sink_event"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool SinkEventNativeDelegate (IntPtr inst, IntPtr evnt);

		static bool SinkEvent_cb (IntPtr inst, IntPtr evnt)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnSinkEvent (evnt == IntPtr.Zero ? null : (Gst.Event) GLib.Opaque.GetOpaque (evnt, typeof (Gst.Event), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideSinkEvent")]
		protected virtual bool OnSinkEvent (Gst.Event evnt)
		{
			return InternalSinkEvent (evnt);
		}

		private bool InternalSinkEvent (Gst.Event evnt)
		{
			SinkEventNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("sink_event"));
				unmanaged = (SinkEventNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(SinkEventNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, evnt == null ? IntPtr.Zero : evnt.Handle);
			return __result;
		}

		static SrcEventNativeDelegate SrcEvent_cb_delegate;
		static SrcEventNativeDelegate SrcEventVMCallback {
			get {
				if (SrcEvent_cb_delegate == null)
					SrcEvent_cb_delegate = new SrcEventNativeDelegate (SrcEvent_cb);
				return SrcEvent_cb_delegate;
			}
		}

		static void OverrideSrcEvent (GLib.GType gtype)
		{
			OverrideSrcEvent (gtype, SrcEventVMCallback);
		}

		static void OverrideSrcEvent (GLib.GType gtype, SrcEventNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("src_event"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool SrcEventNativeDelegate (IntPtr inst, IntPtr evnt);

		static bool SrcEvent_cb (IntPtr inst, IntPtr evnt)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnSrcEvent (evnt == IntPtr.Zero ? null : (Gst.Event) GLib.Opaque.GetOpaque (evnt, typeof (Gst.Event), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideSrcEvent")]
		protected virtual bool OnSrcEvent (Gst.Event evnt)
		{
			return InternalSrcEvent (evnt);
		}

		private bool InternalSrcEvent (Gst.Event evnt)
		{
			SrcEventNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("src_event"));
				unmanaged = (SrcEventNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(SrcEventNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, evnt == null ? IntPtr.Zero : evnt.Handle);
			return __result;
		}

		static OpenNativeDelegate Open_cb_delegate;
		static OpenNativeDelegate OpenVMCallback {
			get {
				if (Open_cb_delegate == null)
					Open_cb_delegate = new OpenNativeDelegate (Open_cb);
				return Open_cb_delegate;
			}
		}

		static void OverrideOpen (GLib.GType gtype)
		{
			OverrideOpen (gtype, OpenVMCallback);
		}

		static void OverrideOpen (GLib.GType gtype, OpenNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("open"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool OpenNativeDelegate (IntPtr inst);

		static bool Open_cb (IntPtr inst)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnOpen ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideOpen")]
		protected virtual bool OnOpen ()
		{
			return InternalOpen ();
		}

		private bool InternalOpen ()
		{
			OpenNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("open"));
				unmanaged = (OpenNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(OpenNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static CloseNativeDelegate Close_cb_delegate;
		static CloseNativeDelegate CloseVMCallback {
			get {
				if (Close_cb_delegate == null)
					Close_cb_delegate = new CloseNativeDelegate (Close_cb);
				return Close_cb_delegate;
			}
		}

		static void OverrideClose (GLib.GType gtype)
		{
			OverrideClose (gtype, CloseVMCallback);
		}

		static void OverrideClose (GLib.GType gtype, CloseNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("close"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool CloseNativeDelegate (IntPtr inst);

		static bool Close_cb (IntPtr inst)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnClose ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideClose")]
		protected virtual bool OnClose ()
		{
			return InternalClose ();
		}

		private bool InternalClose ()
		{
			CloseNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("close"));
				unmanaged = (CloseNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(CloseNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static NegotiateNativeDelegate Negotiate_cb_delegate;
		static NegotiateNativeDelegate NegotiateVMCallback {
			get {
				if (Negotiate_cb_delegate == null)
					Negotiate_cb_delegate = new NegotiateNativeDelegate (Negotiate_cb);
				return Negotiate_cb_delegate;
			}
		}

		static void OverrideNegotiate (GLib.GType gtype)
		{
			OverrideNegotiate (gtype, NegotiateVMCallback);
		}

		static void OverrideNegotiate (GLib.GType gtype, NegotiateNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("negotiate"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool NegotiateNativeDelegate (IntPtr inst);

		static bool Negotiate_cb (IntPtr inst)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnNegotiate ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideNegotiate")]
		protected virtual bool OnNegotiate ()
		{
			return InternalNegotiate ();
		}

		private bool InternalNegotiate ()
		{
			NegotiateNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("negotiate"));
				unmanaged = (NegotiateNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(NegotiateNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static DecideAllocationNativeDelegate DecideAllocation_cb_delegate;
		static DecideAllocationNativeDelegate DecideAllocationVMCallback {
			get {
				if (DecideAllocation_cb_delegate == null)
					DecideAllocation_cb_delegate = new DecideAllocationNativeDelegate (DecideAllocation_cb);
				return DecideAllocation_cb_delegate;
			}
		}

		static void OverrideDecideAllocation (GLib.GType gtype)
		{
			OverrideDecideAllocation (gtype, DecideAllocationVMCallback);
		}

		static void OverrideDecideAllocation (GLib.GType gtype, DecideAllocationNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("decide_allocation"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool DecideAllocationNativeDelegate (IntPtr inst, IntPtr query);

		static bool DecideAllocation_cb (IntPtr inst, IntPtr query)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnDecideAllocation (query == IntPtr.Zero ? null : (Gst.Query) GLib.Opaque.GetOpaque (query, typeof (Gst.Query), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideDecideAllocation")]
		protected virtual bool OnDecideAllocation (Gst.Query query)
		{
			return InternalDecideAllocation (query);
		}

		private bool InternalDecideAllocation (Gst.Query query)
		{
			DecideAllocationNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("decide_allocation"));
				unmanaged = (DecideAllocationNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(DecideAllocationNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, query == null ? IntPtr.Zero : query.Handle);
			return __result;
		}

		static ProposeAllocationNativeDelegate ProposeAllocation_cb_delegate;
		static ProposeAllocationNativeDelegate ProposeAllocationVMCallback {
			get {
				if (ProposeAllocation_cb_delegate == null)
					ProposeAllocation_cb_delegate = new ProposeAllocationNativeDelegate (ProposeAllocation_cb);
				return ProposeAllocation_cb_delegate;
			}
		}

		static void OverrideProposeAllocation (GLib.GType gtype)
		{
			OverrideProposeAllocation (gtype, ProposeAllocationVMCallback);
		}

		static void OverrideProposeAllocation (GLib.GType gtype, ProposeAllocationNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("propose_allocation"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool ProposeAllocationNativeDelegate (IntPtr inst, IntPtr query);

		static bool ProposeAllocation_cb (IntPtr inst, IntPtr query)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnProposeAllocation (query == IntPtr.Zero ? null : (Gst.Query) GLib.Opaque.GetOpaque (query, typeof (Gst.Query), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideProposeAllocation")]
		protected virtual bool OnProposeAllocation (Gst.Query query)
		{
			return InternalProposeAllocation (query);
		}

		private bool InternalProposeAllocation (Gst.Query query)
		{
			ProposeAllocationNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("propose_allocation"));
				unmanaged = (ProposeAllocationNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(ProposeAllocationNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, query == null ? IntPtr.Zero : query.Handle);
			return __result;
		}

		static SinkQueryNativeDelegate SinkQuery_cb_delegate;
		static SinkQueryNativeDelegate SinkQueryVMCallback {
			get {
				if (SinkQuery_cb_delegate == null)
					SinkQuery_cb_delegate = new SinkQueryNativeDelegate (SinkQuery_cb);
				return SinkQuery_cb_delegate;
			}
		}

		static void OverrideSinkQuery (GLib.GType gtype)
		{
			OverrideSinkQuery (gtype, SinkQueryVMCallback);
		}

		static void OverrideSinkQuery (GLib.GType gtype, SinkQueryNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("sink_query"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool SinkQueryNativeDelegate (IntPtr inst, IntPtr query);

		static bool SinkQuery_cb (IntPtr inst, IntPtr query)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnSinkQuery (query == IntPtr.Zero ? null : (Gst.Query) GLib.Opaque.GetOpaque (query, typeof (Gst.Query), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideSinkQuery")]
		protected virtual bool OnSinkQuery (Gst.Query query)
		{
			return InternalSinkQuery (query);
		}

		private bool InternalSinkQuery (Gst.Query query)
		{
			SinkQueryNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("sink_query"));
				unmanaged = (SinkQueryNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(SinkQueryNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, query == null ? IntPtr.Zero : query.Handle);
			return __result;
		}

		static SrcQueryNativeDelegate SrcQuery_cb_delegate;
		static SrcQueryNativeDelegate SrcQueryVMCallback {
			get {
				if (SrcQuery_cb_delegate == null)
					SrcQuery_cb_delegate = new SrcQueryNativeDelegate (SrcQuery_cb);
				return SrcQuery_cb_delegate;
			}
		}

		static void OverrideSrcQuery (GLib.GType gtype)
		{
			OverrideSrcQuery (gtype, SrcQueryVMCallback);
		}

		static void OverrideSrcQuery (GLib.GType gtype, SrcQueryNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("src_query"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool SrcQueryNativeDelegate (IntPtr inst, IntPtr query);

		static bool SrcQuery_cb (IntPtr inst, IntPtr query)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnSrcQuery (query == IntPtr.Zero ? null : (Gst.Query) GLib.Opaque.GetOpaque (query, typeof (Gst.Query), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideSrcQuery")]
		protected virtual bool OnSrcQuery (Gst.Query query)
		{
			return InternalSrcQuery (query);
		}

		private bool InternalSrcQuery (Gst.Query query)
		{
			SrcQueryNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("src_query"));
				unmanaged = (SrcQueryNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(SrcQueryNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, query == null ? IntPtr.Zero : query.Handle);
			return __result;
		}

		static GetcapsNativeDelegate Getcaps_cb_delegate;
		static GetcapsNativeDelegate GetcapsVMCallback {
			get {
				if (Getcaps_cb_delegate == null)
					Getcaps_cb_delegate = new GetcapsNativeDelegate (Getcaps_cb);
				return Getcaps_cb_delegate;
			}
		}

		static void OverrideGetcaps (GLib.GType gtype)
		{
			OverrideGetcaps (gtype, GetcapsVMCallback);
		}

		static void OverrideGetcaps (GLib.GType gtype, GetcapsNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("getcaps"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate IntPtr GetcapsNativeDelegate (IntPtr inst, IntPtr filter);

		static IntPtr Getcaps_cb (IntPtr inst, IntPtr filter)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				Gst.Caps __result;
				__result = __obj.OnGetcaps (filter == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (filter, typeof (Gst.Caps), false));
				return __result == null ? IntPtr.Zero : __result.OwnedCopy;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideGetcaps")]
		protected virtual Gst.Caps OnGetcaps (Gst.Caps filter)
		{
			return InternalGetcaps (filter);
		}

		private Gst.Caps InternalGetcaps (Gst.Caps filter)
		{
			GetcapsNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("getcaps"));
				unmanaged = (GetcapsNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(GetcapsNativeDelegate));
			}
			if (unmanaged == null) return null;

			IntPtr __result = unmanaged (this.Handle, filter == null ? IntPtr.Zero : filter.Handle);
			return __result == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (__result, typeof (Gst.Caps), true);
		}

		static TransformMetaNativeDelegate TransformMeta_cb_delegate;
		static TransformMetaNativeDelegate TransformMetaVMCallback {
			get {
				if (TransformMeta_cb_delegate == null)
					TransformMeta_cb_delegate = new TransformMetaNativeDelegate (TransformMeta_cb);
				return TransformMeta_cb_delegate;
			}
		}

		static void OverrideTransformMeta (GLib.GType gtype)
		{
			OverrideTransformMeta (gtype, TransformMetaVMCallback);
		}

		static void OverrideTransformMeta (GLib.GType gtype, TransformMetaNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("transform_meta"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool TransformMetaNativeDelegate (IntPtr inst, IntPtr outbuf, IntPtr meta, IntPtr inbuf);

		static bool TransformMeta_cb (IntPtr inst, IntPtr outbuf, IntPtr meta, IntPtr inbuf)
		{
			try {
				AudioDecoder __obj = GLib.Object.GetObject (inst, false) as AudioDecoder;
				bool __result;
				__result = __obj.OnTransformMeta (outbuf == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (outbuf, typeof (Gst.Buffer), false), Gst.Meta.New (meta), inbuf == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (inbuf, typeof (Gst.Buffer), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Audio.AudioDecoder), ConnectionMethod="OverrideTransformMeta")]
		protected virtual bool OnTransformMeta (Gst.Buffer outbuf, Gst.Meta meta, Gst.Buffer inbuf)
		{
			return InternalTransformMeta (outbuf, meta, inbuf);
		}

		private bool InternalTransformMeta (Gst.Buffer outbuf, Gst.Meta meta, Gst.Buffer inbuf)
		{
			TransformMetaNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("transform_meta"));
				unmanaged = (TransformMetaNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(TransformMetaNativeDelegate));
			}
			if (unmanaged == null) return false;

			IntPtr native_meta = GLib.Marshaller.StructureToPtrAlloc (meta);
			bool __result = unmanaged (this.Handle, outbuf == null ? IntPtr.Zero : outbuf.Handle, native_meta, inbuf == null ? IntPtr.Zero : inbuf.Handle);
			Marshal.FreeHGlobal (native_meta);
			return __result;
		}


		// Internal representation of the wrapped structure ABI.
		static GLib.AbiStruct _class_abi = null;
		static public new GLib.AbiStruct class_abi {
			get {
				if (_class_abi == null)
					_class_abi = new GLib.AbiStruct (new List<GLib.AbiField>{ 
						new GLib.AbiField("start"
							, Gst.Element.class_abi.Fields
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // start
							, null
							, "stop"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("stop"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // stop
							, "start"
							, "set_format"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("set_format"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // set_format
							, "stop"
							, "parse"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("parse"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // parse
							, "set_format"
							, "handle_frame"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("handle_frame"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // handle_frame
							, "parse"
							, "flush"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("flush"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // flush
							, "handle_frame"
							, "pre_push"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("pre_push"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // pre_push
							, "flush"
							, "sink_event"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("sink_event"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // sink_event
							, "pre_push"
							, "src_event"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("src_event"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // src_event
							, "sink_event"
							, "open"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("open"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // open
							, "src_event"
							, "close"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("close"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // close
							, "open"
							, "negotiate"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("negotiate"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // negotiate
							, "close"
							, "decide_allocation"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("decide_allocation"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // decide_allocation
							, "negotiate"
							, "propose_allocation"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("propose_allocation"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // propose_allocation
							, "decide_allocation"
							, "sink_query"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("sink_query"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // sink_query
							, "propose_allocation"
							, "src_query"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("src_query"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // src_query
							, "sink_query"
							, "getcaps"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("getcaps"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // getcaps
							, "src_query"
							, "transform_meta"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("transform_meta"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // transform_meta
							, "getcaps"
							, "_gst_reserved"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("_gst_reserved"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) * 16 // _gst_reserved
							, "transform_meta"
							, null
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
					});

				return _class_abi;
			}
		}


		// End of the ABI representation.

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_audio_decoder_get_type();

		public static new GLib.GType GType { 
			get {
				IntPtr raw_ret = gst_audio_decoder_get_type();
				GLib.GType ret = new GLib.GType(raw_ret);
				return ret;
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_audio_decoder_allocate_output_buffer(IntPtr raw, UIntPtr size);

		public Gst.Buffer AllocateOutputBuffer(ulong size) {
			IntPtr raw_ret = gst_audio_decoder_allocate_output_buffer(Handle, new UIntPtr (size));
			Gst.Buffer ret = raw_ret == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (raw_ret, typeof (Gst.Buffer), true);
			return ret;
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern int gst_audio_decoder_finish_frame(IntPtr raw, IntPtr buf, int frames);

		public Gst.FlowReturn FinishFrame(Gst.Buffer buf, int frames) {
			buf.Owned = false;
			int raw_ret = gst_audio_decoder_finish_frame(Handle, buf == null ? IntPtr.Zero : buf.Handle, frames);
			Gst.FlowReturn ret = (Gst.FlowReturn) raw_ret;
			return ret;
		}

		public Gst.FlowReturn FinishFrame(int frames) {
			return FinishFrame (null, frames);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern int gst_audio_decoder_finish_subframe(IntPtr raw, IntPtr buf);

		public Gst.FlowReturn FinishSubframe(Gst.Buffer buf) {
			buf.Owned = false;
			int raw_ret = gst_audio_decoder_finish_subframe(Handle, buf == null ? IntPtr.Zero : buf.Handle);
			Gst.FlowReturn ret = (Gst.FlowReturn) raw_ret;
			return ret;
		}

		public Gst.FlowReturn FinishSubframe() {
			return FinishSubframe (null);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_get_allocator(IntPtr raw, out IntPtr allocator, IntPtr parms);

		public void GetAllocator(out Gst.Allocator allocator, out Gst.AllocationParams parms) {
			IntPtr native_allocator;
			IntPtr native_parms = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (Gst.AllocationParams)));
			gst_audio_decoder_get_allocator(Handle, out native_allocator, native_parms);
			allocator = GLib.Object.GetObject(native_allocator, true) as Gst.Allocator;
			parms = Gst.AllocationParams.New (native_parms);
			Marshal.FreeHGlobal (native_parms);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_audio_decoder_get_audio_info(IntPtr raw);

		public Gst.Audio.AudioInfo AudioInfo { 
			get {
				IntPtr raw_ret = gst_audio_decoder_get_audio_info(Handle);
				Gst.Audio.AudioInfo ret = raw_ret == IntPtr.Zero ? null : (Gst.Audio.AudioInfo) GLib.Opaque.GetOpaque (raw_ret, typeof (Gst.Audio.AudioInfo), false);
				return ret;
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern int gst_audio_decoder_get_delay(IntPtr raw);

		public int Delay { 
			get {
				int raw_ret = gst_audio_decoder_get_delay(Handle);
				int ret = raw_ret;
				return ret;
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_audio_decoder_get_drainable(IntPtr raw);

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_drainable(IntPtr raw, bool enabled);

		public bool Drainable { 
			get {
				bool raw_ret = gst_audio_decoder_get_drainable(Handle);
				bool ret = raw_ret;
				return ret;
			}
			set {
				gst_audio_decoder_set_drainable(Handle, value);
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern int gst_audio_decoder_get_estimate_rate(IntPtr raw);

		public int EstimateRate { 
			get {
				int raw_ret = gst_audio_decoder_get_estimate_rate(Handle);
				int ret = raw_ret;
				return ret;
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_get_latency(IntPtr raw, out ulong min, out ulong max);

		public void GetLatency(out ulong min, out ulong max) {
			gst_audio_decoder_get_latency(Handle, out min, out max);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_audio_decoder_get_needs_format(IntPtr raw);

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_needs_format(IntPtr raw, bool enabled);

		public bool NeedsFormat { 
			get {
				bool raw_ret = gst_audio_decoder_get_needs_format(Handle);
				bool ret = raw_ret;
				return ret;
			}
			set {
				gst_audio_decoder_set_needs_format(Handle, value);
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_get_parse_state(IntPtr raw, out bool sync, out bool eos);

		public void GetParseState(out bool sync, out bool eos) {
			gst_audio_decoder_get_parse_state(Handle, out sync, out eos);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern int gst_audio_decoder_get_plc_aware(IntPtr raw);

		public int PlcAware { 
			get {
				int raw_ret = gst_audio_decoder_get_plc_aware(Handle);
				int ret = raw_ret;
				return ret;
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_merge_tags(IntPtr raw, IntPtr tags, int mode);

		public void MergeTags(Gst.TagList tags, Gst.TagMergeMode mode) {
			gst_audio_decoder_merge_tags(Handle, tags == null ? IntPtr.Zero : tags.Handle, (int) mode);
		}

		public void MergeTags(Gst.TagMergeMode mode) {
			MergeTags (null, mode);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_audio_decoder_negotiate(IntPtr raw);

		public bool Negotiate() {
			bool raw_ret = gst_audio_decoder_negotiate(Handle);
			bool ret = raw_ret;
			return ret;
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_audio_decoder_proxy_getcaps(IntPtr raw, IntPtr caps, IntPtr filter);

		public Gst.Caps ProxyGetcaps(Gst.Caps caps, Gst.Caps filter) {
			IntPtr raw_ret = gst_audio_decoder_proxy_getcaps(Handle, caps == null ? IntPtr.Zero : caps.Handle, filter == null ? IntPtr.Zero : filter.Handle);
			Gst.Caps ret = raw_ret == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (raw_ret, typeof (Gst.Caps), true);
			return ret;
		}

		public Gst.Caps ProxyGetcaps() {
			return ProxyGetcaps (null, null);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_allocation_caps(IntPtr raw, IntPtr allocation_caps);

		public Gst.Caps AllocationCaps { 
			set {
				gst_audio_decoder_set_allocation_caps(Handle, value == null ? IntPtr.Zero : value.Handle);
			}
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_estimate_rate(IntPtr raw, bool enabled);

		public void SetEstimateRate(bool enabled) {
			gst_audio_decoder_set_estimate_rate(Handle, enabled);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_latency(IntPtr raw, ulong min, ulong max);

		public void SetLatency(ulong min, ulong max) {
			gst_audio_decoder_set_latency(Handle, min, max);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_audio_decoder_set_output_caps(IntPtr raw, IntPtr caps);

		public bool SetOutputCaps(Gst.Caps caps) {
			bool raw_ret = gst_audio_decoder_set_output_caps(Handle, caps == null ? IntPtr.Zero : caps.Handle);
			bool ret = raw_ret;
			return ret;
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_audio_decoder_set_output_format(IntPtr raw, IntPtr info);

		public bool SetOutputFormat(Gst.Audio.AudioInfo info) {
			bool raw_ret = gst_audio_decoder_set_output_format(Handle, info == null ? IntPtr.Zero : info.Handle);
			bool ret = raw_ret;
			return ret;
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_plc_aware(IntPtr raw, bool plc);

		public void SetPlcAware(bool plc) {
			gst_audio_decoder_set_plc_aware(Handle, plc);
		}

		[DllImport("gstaudio-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_audio_decoder_set_use_default_pad_acceptcaps(IntPtr raw, bool use);

		public bool UseDefaultPadAcceptcaps { 
			set {
				gst_audio_decoder_set_use_default_pad_acceptcaps(Handle, value);
			}
		}


		static AudioDecoder ()
		{
			GtkSharp.GstreamerSharp.ObjectManager.Initialize ();
		}

		// Internal representation of the wrapped structure ABI.
		static GLib.AbiStruct _abi_info = null;
		static public new GLib.AbiStruct abi_info {
			get {
				if (_abi_info == null)
					_abi_info = new GLib.AbiStruct (new List<GLib.AbiField>{ 
						new GLib.AbiField("sinkpad"
							, Gst.Element.abi_info.Fields
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // sinkpad
							, null
							, "srcpad"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("srcpad"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // srcpad
							, "sinkpad"
							, "stream_lock"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("stream_lock"
							, -1
							, (uint) Marshal.SizeOf(typeof(GLib.RecMutex.ABI)) // stream_lock
							, "srcpad"
							, "input_segment"
							, (long) Marshal.OffsetOf(typeof(GstAudioDecoder_stream_lockAlign), "stream_lock")
							, 0
							),
						new GLib.AbiField("input_segment"
							, -1
							, (uint) Marshal.SizeOf(typeof(Gst.Segment)) // input_segment
							, "stream_lock"
							, "output_segment"
							, (long) Marshal.OffsetOf(typeof(GstAudioDecoder_input_segmentAlign), "input_segment")
							, 0
							),
						new GLib.AbiField("output_segment"
							, -1
							, (uint) Marshal.SizeOf(typeof(Gst.Segment)) // output_segment
							, "input_segment"
							, "priv"
							, (long) Marshal.OffsetOf(typeof(GstAudioDecoder_output_segmentAlign), "output_segment")
							, 0
							),
						new GLib.AbiField("priv"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // priv
							, "output_segment"
							, "_gst_reserved"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("_gst_reserved"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) * 20 // _gst_reserved
							, "priv"
							, null
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
					});

				return _abi_info;
			}
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstAudioDecoder_stream_lockAlign
		{
			sbyte f1;
			private GLib.RecMutex.ABI stream_lock;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstAudioDecoder_input_segmentAlign
		{
			sbyte f1;
			private Gst.Segment input_segment;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstAudioDecoder_output_segmentAlign
		{
			sbyte f1;
			private Gst.Segment output_segment;
		}


		// End of the ABI representation.

#endregion
	}
}
