// 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 ProxyControlBinding : Gst.ControlBinding {

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

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

		public ProxyControlBinding (Gst.Object _object, string property_name, Gst.Object ref_object, string ref_property_name) : base (IntPtr.Zero)
		{
			if (GetType () != typeof (ProxyControlBinding)) {
				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);
			IntPtr native_ref_property_name = GLib.Marshaller.StringToPtrGStrdup (ref_property_name);
			Raw = gst_proxy_control_binding_new(_object == null ? IntPtr.Zero : _object.Handle, native_property_name, ref_object == null ? IntPtr.Zero : ref_object.Handle, native_ref_property_name);
			GLib.Marshaller.Free (native_property_name);
			GLib.Marshaller.Free (native_ref_property_name);
		}


		// 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("_padding"
							, Gst.ControlBinding.class_abi.Fields
							, (uint) Marshal.SizeOf(typeof(IntPtr)) * 4 // _padding
							, 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_proxy_control_binding_get_type();

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


		static ProxyControlBinding ()
		{
			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("ref_object"
							, Gst.ControlBinding.abi_info.Fields
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // ref_object
							, null
							, "property_name"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("property_name"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // property_name
							, "ref_object"
							, "_padding"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("_padding"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) * 4 // _padding
							, "property_name"
							, null
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
					});

				return _abi_info;
			}
		}


		// End of the ABI representation.

#endregion
	}
}
