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

namespace Gst.Video {

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

#region Autogenerated code
	[StructLayout(LayoutKind.Sequential)]
	public partial struct VideoVBIEncoder : IEquatable<VideoVBIEncoder> {


		public static Gst.Video.VideoVBIEncoder Zero = new Gst.Video.VideoVBIEncoder ();

		public static Gst.Video.VideoVBIEncoder New(IntPtr raw) {
			if (raw == IntPtr.Zero)
				return Gst.Video.VideoVBIEncoder.Zero;
			return (Gst.Video.VideoVBIEncoder) Marshal.PtrToStructure (raw, typeof (Gst.Video.VideoVBIEncoder));
		}

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_video_vbi_encoder_new(int format, uint pixel_width);

		public static VideoVBIEncoder New(Gst.Video.VideoFormat format, uint pixel_width)
		{
			VideoVBIEncoder result = VideoVBIEncoder.New (gst_video_vbi_encoder_new((int) format, pixel_width));
			return result;
		}

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

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

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_video_vbi_encoder_add_ancillary(IntPtr raw, bool composite, byte DID, byte SDID_block_number, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=5)]byte[] data, uint data_count);

		public bool AddAncillary(bool composite, byte DID, byte SDID_block_number, byte[] data) {
			IntPtr this_as_native = System.Runtime.InteropServices.Marshal.AllocHGlobal (System.Runtime.InteropServices.Marshal.SizeOf (this));
			System.Runtime.InteropServices.Marshal.StructureToPtr (this, this_as_native, false);
			uint data_count = (uint)(data == null ? 0 : data.Length);
			bool raw_ret = gst_video_vbi_encoder_add_ancillary(this_as_native, composite, DID, SDID_block_number, data, data_count);
			bool ret = raw_ret;
			ReadNative (this_as_native, ref this);
			System.Runtime.InteropServices.Marshal.FreeHGlobal (this_as_native);
			return ret;
		}

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_video_vbi_encoder_write_line(IntPtr raw, byte data);

		public void WriteLine(byte data) {
			IntPtr this_as_native = System.Runtime.InteropServices.Marshal.AllocHGlobal (System.Runtime.InteropServices.Marshal.SizeOf (this));
			System.Runtime.InteropServices.Marshal.StructureToPtr (this, this_as_native, false);
			gst_video_vbi_encoder_write_line(this_as_native, data);
			ReadNative (this_as_native, ref this);
			System.Runtime.InteropServices.Marshal.FreeHGlobal (this_as_native);
		}

		static void ReadNative (IntPtr native, ref Gst.Video.VideoVBIEncoder target)
		{
			target = New (native);
		}

		public bool Equals (VideoVBIEncoder other)
		{
			return true;
		}

		public override bool Equals (object other)
		{
			return other is VideoVBIEncoder && Equals ((VideoVBIEncoder) other);
		}

		public override int GetHashCode ()
		{
			return this.GetType ().FullName.GetHashCode ();
		}

		public static explicit operator GLib.Value (Gst.Video.VideoVBIEncoder boxed)
		{
			GLib.Value val = GLib.Value.Empty;
			val.Init (Gst.Video.VideoVBIEncoder.GType);
			val.Val = boxed;
			return val;
		}

		public static explicit operator Gst.Video.VideoVBIEncoder (GLib.Value val)
		{
			return (Gst.Video.VideoVBIEncoder) val.Val;
		}
#endregion
	}
}
