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

namespace Gst.Net {

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

#region Autogenerated code
	public partial class NetClientClock : Gst.SystemClock {

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

		[DllImport("gstnet-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_net_client_clock_new(IntPtr name, IntPtr remote_address, int remote_port, ulong base_time);

		public NetClientClock (string name, string remote_address, int remote_port, ulong base_time) : base (IntPtr.Zero)
		{
			if (GetType () != typeof (NetClientClock)) {
				var vals = new List<GLib.Value> ();
				var names = new List<string> ();
				names.Add ("name");
				vals.Add (new GLib.Value (name));
				names.Add ("base_time");
				vals.Add (new GLib.Value (base_time));
				CreateNativeObject (names.ToArray (), vals.ToArray ());
				return;
			}
			IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name);
			IntPtr native_remote_address = GLib.Marshaller.StringToPtrGStrdup (remote_address);
			Raw = gst_net_client_clock_new(native_name, native_remote_address, remote_port, base_time);
			GLib.Marshaller.Free (native_name);
			GLib.Marshaller.Free (native_remote_address);
		}

		[GLib.Property ("address")]
		public string Address {
			get {
				GLib.Value val = GetProperty ("address");
				string ret = (string) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value);
				SetProperty("address", val);
				val.Dispose ();
			}
		}

		[GLib.Property ("base-time")]
		public ulong BaseTime {
			get {
				GLib.Value val = GetProperty ("base-time");
				ulong ret = (ulong) val;
				val.Dispose ();
				return ret;
			}
		}

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

		[GLib.Property ("internal-clock")]
		public Gst.Clock InternalClock {
			get {
				GLib.Value val = GetProperty ("internal-clock");
				Gst.Clock ret = (Gst.Clock) val;
				val.Dispose ();
				return ret;
			}
		}

		[GLib.Property ("minimum-update-interval")]
		public ulong MinimumUpdateInterval {
			get {
				GLib.Value val = GetProperty ("minimum-update-interval");
				ulong ret = (ulong) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value);
				SetProperty("minimum-update-interval", val);
				val.Dispose ();
			}
		}

		[GLib.Property ("port")]
		public int Port {
			get {
				GLib.Value val = GetProperty ("port");
				int ret = (int) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value);
				SetProperty("port", val);
				val.Dispose ();
			}
		}

		[GLib.Property ("qos-dscp")]
		public int QosDscp {
			get {
				GLib.Value val = GetProperty ("qos-dscp");
				int ret = (int) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value);
				SetProperty("qos-dscp", val);
				val.Dispose ();
			}
		}

		[GLib.Property ("round-trip-limit")]
		public ulong RoundTripLimit {
			get {
				GLib.Value val = GetProperty ("round-trip-limit");
				ulong ret = (ulong) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value);
				SetProperty("round-trip-limit", 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.SystemClock.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("gstnet-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_net_client_clock_get_type();

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


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

				return _abi_info;
			}
		}


		// End of the ABI representation.

#endregion
	}
}
