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

namespace Gst.Controller {

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

#region Autogenerated code
	public partial class DirectControlBinding : Gst.ControlBinding {

		public DirectControlBinding (IntPtr raw) : base(raw) {}

		[DllImport("gstcontroller-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_direct_control_binding_new(IntPtr _object, IntPtr property_name, IntPtr cs);

		public DirectControlBinding (Gst.Object _object, string property_name, Gst.ControlSource cs) : base (IntPtr.Zero)
		{
			if (GetType () != typeof (DirectControlBinding)) {
				var vals = new List<GLib.Value> ();
				var names = new List<string> ();
				if (_object != null) {
					names.Add ("_object");
					vals.Add (new GLib.Value (_object));
				}
				CreateNativeObject (names.ToArray (), vals.ToArray ());
				return;
			}
			IntPtr native_property_name = GLib.Marshaller.StringToPtrGStrdup (property_name);
			Raw = gst_direct_control_binding_new(_object == null ? IntPtr.Zero : _object.Handle, native_property_name, cs == null ? IntPtr.Zero : cs.Handle);
			GLib.Marshaller.Free (native_property_name);
		}

		[DllImport("gstcontroller-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_direct_control_binding_new_absolute(IntPtr _object, IntPtr property_name, IntPtr cs);

		public static DirectControlBinding NewAbsolute(Gst.Object _object, string property_name, Gst.ControlSource cs)
		{
			IntPtr native_property_name = GLib.Marshaller.StringToPtrGStrdup (property_name);
			DirectControlBinding result = new DirectControlBinding (gst_direct_control_binding_new_absolute(_object == null ? IntPtr.Zero : _object.Handle, native_property_name, cs == null ? IntPtr.Zero : cs.Handle));
			GLib.Marshaller.Free (native_property_name);
			return result;
		}

		[GLib.Property ("absolute")]
		public bool Absolute {
			get {
				GLib.Value val = GetProperty ("absolute");
				bool ret = (bool) val;
				val.Dispose ();
				return ret;
			}
		}

		[GLib.Property ("control-source")]
		public Gst.ControlSource ControlSource {
			get {
				GLib.Value val = GetProperty ("control-source");
				Gst.ControlSource ret = (Gst.ControlSource) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value);
				SetProperty("control-source", val);
				val.Dispose ();
			}
		}


		// 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.ControlBinding.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("gstcontroller-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_direct_control_binding_get_type();

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


		static DirectControlBinding ()
		{
			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("cs"
							, Gst.ControlBinding.abi_info.Fields
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // cs
							, null
							, "cur_value"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("cur_value"
							, -1
							, (uint) Marshal.SizeOf(typeof(GLib.Value)) // cur_value
							, "cs"
							, "last_value"
							, (long) Marshal.OffsetOf(typeof(GstDirectControlBinding_cur_valueAlign), "cur_value")
							, 0
							),
						new GLib.AbiField("last_value"
							, -1
							, (uint) Marshal.SizeOf(typeof(double)) // last_value
							, "cur_value"
							, "byte_size"
							, (long) Marshal.OffsetOf(typeof(GstDirectControlBinding_last_valueAlign), "last_value")
							, 0
							),
						new GLib.AbiField("byte_size"
							, -1
							, (uint) Marshal.SizeOf(typeof(int)) // byte_size
							, "last_value"
							, "convert_value"
							, (long) Marshal.OffsetOf(typeof(GstDirectControlBinding_byte_sizeAlign), "byte_size")
							, 0
							),
						new GLib.AbiField("convert_value"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // convert_value
							, "byte_size"
							, "convert_g_value"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("convert_g_value"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // convert_g_value
							, "convert_value"
							, "ABI"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						// union struct ABI
							new GLib.AbiField("ABI._gst_reserved"
								, -1
								, (uint) Marshal.SizeOf(typeof(IntPtr)) * 4 // ABI._gst_reserved
								, "convert_g_value"
								, null
								, (uint) Marshal.SizeOf(typeof(IntPtr))
								, 0
								),
						// End ABI

						// union struct ABI.abi
							new GLib.AbiField("ABI.abi.want_absolute"
								, -1
								, (uint) Marshal.SizeOf(typeof(bool)) // ABI.abi.want_absolute
								, "convert_g_value"
								, null
								, (long) Marshal.OffsetOf(typeof(GstDirectControlBinding_ABI_abi_want_absoluteAlign), "ABI_abi_want_absolute")
								, 0
								),
						// End ABI.abi

						new GLib.AbiField("ABI"
							, -1
							, new List<List<string>>() {  // union ABI
						new List<string>() {"ABI._gst_reserved"},
						new List<string>() {"ABI.abi.want_absolute"}
					  }
							, "convert_g_value"
							, null
							, 0
							),
					});

				return _abi_info;
			}
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstDirectControlBinding_cur_valueAlign
		{
			sbyte f1;
			private GLib.Value cur_value;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstDirectControlBinding_last_valueAlign
		{
			sbyte f1;
			private double last_value;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstDirectControlBinding_byte_sizeAlign
		{
			sbyte f1;
			private int byte_size;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstDirectControlBinding_ABI_abi_want_absoluteAlign
		{
			sbyte f1;
			private bool ABI_abi_want_absolute;
		}


		// End of the ABI representation.

#endregion
	}
}
