// 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 VideoTimeCodeInterval : IEquatable<VideoTimeCodeInterval> {

		public uint Hours;
		public uint Minutes;
		public uint Seconds;
		public uint Frames;

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

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

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_video_time_code_interval_new(uint hours, uint minutes, uint seconds, uint frames);

		public static VideoTimeCodeInterval New(uint hours, uint minutes, uint seconds, uint frames)
		{
			VideoTimeCodeInterval result = VideoTimeCodeInterval.New (gst_video_time_code_interval_new(hours, minutes, seconds, frames));
			return result;
		}

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

		public static VideoTimeCodeInterval NewFromString(string tc_inter_str)
		{
			IntPtr native_tc_inter_str = GLib.Marshaller.StringToPtrGStrdup (tc_inter_str);
			VideoTimeCodeInterval result = VideoTimeCodeInterval.New (gst_video_time_code_interval_new_from_string(native_tc_inter_str));
			GLib.Marshaller.Free (native_tc_inter_str);
			return result;
		}

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

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

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

		public void Clear() {
			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_time_code_interval_clear(this_as_native);
			ReadNative (this_as_native, ref this);
			System.Runtime.InteropServices.Marshal.FreeHGlobal (this_as_native);
		}

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_video_time_code_interval_init(IntPtr raw, uint hours, uint minutes, uint seconds, uint frames);

		public void Init(uint hours, uint minutes, uint seconds, uint frames) {
			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_time_code_interval_init(this_as_native, hours, minutes, seconds, frames);
			ReadNative (this_as_native, ref this);
			System.Runtime.InteropServices.Marshal.FreeHGlobal (this_as_native);
		}

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

		public bool Equals (VideoTimeCodeInterval other)
		{
			return true && Hours.Equals (other.Hours) && Minutes.Equals (other.Minutes) && Seconds.Equals (other.Seconds) && Frames.Equals (other.Frames);
		}

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

		public override int GetHashCode ()
		{
			return this.GetType ().FullName.GetHashCode () ^ Hours.GetHashCode () ^ Minutes.GetHashCode () ^ Seconds.GetHashCode () ^ Frames.GetHashCode ();
		}

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

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