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

namespace Gst.PbUtils {

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

#region Autogenerated code
	public partial class EncodingProfile : GLib.Object {

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

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

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_get_element_properties(IntPtr raw);

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_element_properties(IntPtr raw, IntPtr element_properties);

		[GLib.Property ("element-properties")]
		public Gst.Structure ElementProperties {
			get  {
				IntPtr raw_ret = gst_encoding_profile_get_element_properties(Handle);
				Gst.Structure ret = raw_ret == IntPtr.Zero ? null : (Gst.Structure) GLib.Opaque.GetOpaque (raw_ret, typeof (Gst.Structure), true);
				return ret;
			}
			set  {
				value.Owned = false;
				gst_encoding_profile_set_element_properties(Handle, value == null ? IntPtr.Zero : value.Handle);
			}
		}

		[GLib.Property ("restriction-caps")]
		public Gst.Caps RestrictionCaps {
			get {
				GLib.Value val = GetProperty ("restriction-caps");
				Gst.Caps ret = (Gst.Caps) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value, "GstCaps*");
				SetProperty("restriction-caps", 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 (GLib.Object.class_abi.Fields);

				return _class_abi;
			}
		}


		// End of the ABI representation.

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

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

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_find(IntPtr targetname, IntPtr profilename, IntPtr category);

		public static Gst.PbUtils.EncodingProfile Find(string targetname, string profilename, string category) {
			IntPtr native_targetname = GLib.Marshaller.StringToPtrGStrdup (targetname);
			IntPtr native_profilename = GLib.Marshaller.StringToPtrGStrdup (profilename);
			IntPtr native_category = GLib.Marshaller.StringToPtrGStrdup (category);
			IntPtr raw_ret = gst_encoding_profile_find(native_targetname, native_profilename, native_category);
			Gst.PbUtils.EncodingProfile ret = GLib.Object.GetObject(raw_ret, true) as Gst.PbUtils.EncodingProfile;
			GLib.Marshaller.Free (native_targetname);
			GLib.Marshaller.Free (native_profilename);
			GLib.Marshaller.Free (native_category);
			return ret;
		}

		public static Gst.PbUtils.EncodingProfile Find(string targetname) {
			return Find (targetname, null, null);
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_from_discoverer(IntPtr info);

		public static Gst.PbUtils.EncodingProfile FromDiscoverer(Gst.PbUtils.DiscovererInfo info) {
			IntPtr raw_ret = gst_encoding_profile_from_discoverer(info == null ? IntPtr.Zero : info.Handle);
			Gst.PbUtils.EncodingProfile ret = GLib.Object.GetObject(raw_ret, true) as Gst.PbUtils.EncodingProfile;
			return ret;
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_copy(IntPtr raw);

		public Gst.PbUtils.EncodingProfile Copy() {
			IntPtr raw_ret = gst_encoding_profile_copy(Handle);
			Gst.PbUtils.EncodingProfile ret = GLib.Object.GetObject(raw_ret, true) as Gst.PbUtils.EncodingProfile;
			return ret;
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_encoding_profile_get_allow_dynamic_output(IntPtr raw);

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_allow_dynamic_output(IntPtr raw, bool allow_dynamic_output);

		public bool AllowDynamicOutput { 
			get {
				bool raw_ret = gst_encoding_profile_get_allow_dynamic_output(Handle);
				bool ret = raw_ret;
				return ret;
			}
			set {
				gst_encoding_profile_set_allow_dynamic_output(Handle, value);
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_get_description(IntPtr raw);

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_description(IntPtr raw, IntPtr description);

		public string Description { 
			get {
				IntPtr raw_ret = gst_encoding_profile_get_description(Handle);
				string ret = GLib.Marshaller.Utf8PtrToString (raw_ret);
				return ret;
			}
			set {
				IntPtr native_value = GLib.Marshaller.StringToPtrGStrdup (value);
				gst_encoding_profile_set_description(Handle, native_value);
				GLib.Marshaller.Free (native_value);
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_get_file_extension(IntPtr raw);

		public string FileExtension { 
			get {
				IntPtr raw_ret = gst_encoding_profile_get_file_extension(Handle);
				string ret = GLib.Marshaller.Utf8PtrToString (raw_ret);
				return ret;
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_get_format(IntPtr raw);

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_format(IntPtr raw, IntPtr format);

		public Gst.Caps Format { 
			get {
				IntPtr raw_ret = gst_encoding_profile_get_format(Handle);
				Gst.Caps ret = raw_ret == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (raw_ret, typeof (Gst.Caps), true);
				return ret;
			}
			set {
				gst_encoding_profile_set_format(Handle, value == null ? IntPtr.Zero : value.Handle);
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_get_input_caps(IntPtr raw);

		public Gst.Caps InputCaps { 
			get {
				IntPtr raw_ret = gst_encoding_profile_get_input_caps(Handle);
				Gst.Caps ret = raw_ret == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (raw_ret, typeof (Gst.Caps), true);
				return ret;
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_get_name(IntPtr raw);

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_name(IntPtr raw, IntPtr name);

		public string Name { 
			get {
				IntPtr raw_ret = gst_encoding_profile_get_name(Handle);
				string ret = GLib.Marshaller.Utf8PtrToString (raw_ret);
				return ret;
			}
			set {
				IntPtr native_value = GLib.Marshaller.StringToPtrGStrdup (value);
				gst_encoding_profile_set_name(Handle, native_value);
				GLib.Marshaller.Free (native_value);
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern uint gst_encoding_profile_get_presence(IntPtr raw);

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_presence(IntPtr raw, uint presence);

		public uint Presence { 
			get {
				uint raw_ret = gst_encoding_profile_get_presence(Handle);
				uint ret = raw_ret;
				return ret;
			}
			set {
				gst_encoding_profile_set_presence(Handle, value);
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_get_preset(IntPtr raw);

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_preset(IntPtr raw, IntPtr preset);

		public string Preset { 
			get {
				IntPtr raw_ret = gst_encoding_profile_get_preset(Handle);
				string ret = GLib.Marshaller.Utf8PtrToString (raw_ret);
				return ret;
			}
			set {
				IntPtr native_value = GLib.Marshaller.StringToPtrGStrdup (value);
				gst_encoding_profile_set_preset(Handle, native_value);
				GLib.Marshaller.Free (native_value);
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_get_preset_name(IntPtr raw);

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_preset_name(IntPtr raw, IntPtr preset_name);

		public string PresetName { 
			get {
				IntPtr raw_ret = gst_encoding_profile_get_preset_name(Handle);
				string ret = GLib.Marshaller.Utf8PtrToString (raw_ret);
				return ret;
			}
			set {
				IntPtr native_value = GLib.Marshaller.StringToPtrGStrdup (value);
				gst_encoding_profile_set_preset_name(Handle, native_value);
				GLib.Marshaller.Free (native_value);
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_get_restriction(IntPtr raw);

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_restriction(IntPtr raw, IntPtr restriction);

		public Gst.Caps Restriction { 
			get {
				IntPtr raw_ret = gst_encoding_profile_get_restriction(Handle);
				Gst.Caps ret = raw_ret == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (raw_ret, typeof (Gst.Caps), true);
				return ret;
			}
			set {
				value.Owned = false;
				gst_encoding_profile_set_restriction(Handle, value == null ? IntPtr.Zero : value.Handle);
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_encoding_profile_get_single_segment(IntPtr raw);

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_single_segment(IntPtr raw, bool single_segment);

		public bool SingleSegment { 
			get {
				bool raw_ret = gst_encoding_profile_get_single_segment(Handle);
				bool ret = raw_ret;
				return ret;
			}
			set {
				gst_encoding_profile_set_single_segment(Handle, value);
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_profile_get_type_nick(IntPtr raw);

		public string TypeNick { 
			get {
				IntPtr raw_ret = gst_encoding_profile_get_type_nick(Handle);
				string ret = GLib.Marshaller.Utf8PtrToString (raw_ret);
				return ret;
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_encoding_profile_is_enabled(IntPtr raw);

		public bool IsEnabled { 
			get {
				bool raw_ret = gst_encoding_profile_is_enabled(Handle);
				bool ret = raw_ret;
				return ret;
			}
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_encoding_profile_is_equal(IntPtr raw, IntPtr b);

		public bool IsEqual(Gst.PbUtils.EncodingProfile b) {
			bool raw_ret = gst_encoding_profile_is_equal(Handle, b == null ? IntPtr.Zero : b.Handle);
			bool ret = raw_ret;
			return ret;
		}

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_encoding_profile_set_enabled(IntPtr raw, bool enabled);

		public bool Enabled { 
			set {
				gst_encoding_profile_set_enabled(Handle, value);
			}
		}


		static EncodingProfile ()
		{
			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 (GLib.Object.abi_info.Fields);

				return _abi_info;
			}
		}


		// End of the ABI representation.

#endregion
	}
}
