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

namespace Gst {

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

#region Autogenerated code
	public partial class ControlSource : Gst.Object {

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

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

		public Gst.ControlSourceGetValue GetValue {
			get {
				unsafe {
					IntPtr* raw_ptr = (IntPtr*)(((byte*)Handle) + abi_info.GetFieldOffset("get_value"));
					 GstSharp.ControlSourceGetValueNative del = (GstSharp.ControlSourceGetValueNative)Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(GstSharp.ControlSourceGetValueNative));
					return GstSharp.ControlSourceGetValueWrapper.GetManagedDelegate ((del));
				}
			}
		}

		public Gst.ControlSourceGetValueArray GetValueArray {
			get {
				unsafe {
					IntPtr* raw_ptr = (IntPtr*)(((byte*)Handle) + abi_info.GetFieldOffset("get_value_array"));
					 GstSharp.ControlSourceGetValueArrayNative del = (GstSharp.ControlSourceGetValueArrayNative)Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(GstSharp.ControlSourceGetValueArrayNative));
					return GstSharp.ControlSourceGetValueArrayWrapper.GetManagedDelegate ((del));
				}
			}
		}


		// 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("_gst_reserved"
							, Gst.Object.class_abi.Fields
							, (uint) Marshal.SizeOf(typeof(IntPtr)) * 4 // _gst_reserved
							, null
							, null
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
					});

				return _class_abi;
			}
		}


		// End of the ABI representation.

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

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

		[DllImport("gstreamer-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_control_source_get_value(IntPtr raw, ulong timestamp, out double value);

		public bool GetValueAt(ulong timestamp, out double value) {
			bool raw_ret = gst_control_source_get_value(Handle, timestamp, out value);
			bool ret = raw_ret;
			return ret;
		}

		[DllImport("gstreamer-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_control_source_get_value_array(IntPtr raw, ulong timestamp, ulong interval, uint n_values, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)]double[] values);

		public bool GetValues(ulong timestamp, ulong interval, double[] values) {
			uint n_values = (uint)(values == null ? 0 : values.Length);
			bool raw_ret = gst_control_source_get_value_array(Handle, timestamp, interval, n_values, values);
			bool ret = raw_ret;
			return ret;
		}


		// 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("get_value"
							, Gst.Object.abi_info.Fields
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // get_value
							, null
							, "get_value_array"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("get_value_array"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // get_value_array
							, "get_value"
							, "_gst_reserved"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("_gst_reserved"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) * 4 // _gst_reserved
							, "get_value_array"
							, null
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
					});

				return _abi_info;
			}
		}


		// End of the ABI representation.

#endregion
	}
}
