// 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 EncodingContainerProfile : Gst.PbUtils.EncodingProfile {

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

		[DllImport("gstpbutils-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_encoding_container_profile_new(IntPtr name, IntPtr description, IntPtr format, IntPtr preset);

		public EncodingContainerProfile (string name, string description, Gst.Caps format, string preset) : base (IntPtr.Zero)
		{
			if (GetType () != typeof (EncodingContainerProfile)) {
				var vals = new List<GLib.Value> ();
				var names = new List<string> ();
				CreateNativeObject (names.ToArray (), vals.ToArray ());
				return;
			}
			IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name);
			IntPtr native_description = GLib.Marshaller.StringToPtrGStrdup (description);
			IntPtr native_preset = GLib.Marshaller.StringToPtrGStrdup (preset);
			Raw = gst_encoding_container_profile_new(native_name, native_description, format == null ? IntPtr.Zero : format.Handle, native_preset);
			GLib.Marshaller.Free (native_name);
			GLib.Marshaller.Free (native_description);
			GLib.Marshaller.Free (native_preset);
		}


		// 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 (Gst.PbUtils.EncodingProfile.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_container_profile_get_type();

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

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

		public bool AddProfile(Gst.PbUtils.EncodingProfile profile) {
			bool raw_ret = gst_encoding_container_profile_add_profile(Handle, profile == null ? IntPtr.Zero : profile.OwnedHandle);
			bool ret = raw_ret;
			return ret;
		}

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

		public bool ContainsProfile(Gst.PbUtils.EncodingProfile profile) {
			bool raw_ret = gst_encoding_container_profile_contains_profile(Handle, profile == null ? IntPtr.Zero : profile.Handle);
			bool ret = raw_ret;
			return ret;
		}

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

		public Gst.PbUtils.EncodingProfile[] Profiles { 
			get {
				IntPtr raw_ret = gst_encoding_container_profile_get_profiles(Handle);
				Gst.PbUtils.EncodingProfile[] ret = (Gst.PbUtils.EncodingProfile[]) GLib.Marshaller.ListPtrToArray (raw_ret, typeof(GLib.List), false, false, typeof(Gst.PbUtils.EncodingProfile));
				return ret;
			}
		}


		static EncodingContainerProfile ()
		{
			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 (Gst.PbUtils.EncodingProfile.abi_info.Fields);

				return _abi_info;
			}
		}


		// End of the ABI representation.

#endregion
	}
}
