// 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 LFOControlSource : Gst.ControlSource {

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

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

		public LFOControlSource () : base (IntPtr.Zero)
		{
			if (GetType () != typeof (LFOControlSource)) {
				CreateNativeObject (new string [0], new GLib.Value[0]);
				return;
			}
			Raw = gst_lfo_control_source_new();
		}

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

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

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

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

		[GLib.Property ("waveform")]
		public Gst.Controller.LFOWaveform Waveform {
			get {
				GLib.Value val = GetProperty ("waveform");
				Gst.Controller.LFOWaveform ret = (Gst.Controller.LFOWaveform) (Enum) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value((Enum) value);
				SetProperty("waveform", 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.ControlSource.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_lfo_control_source_get_type();

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


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

				return _abi_info;
			}
		}


		// End of the ABI representation.

#endregion
	}
}
