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

namespace Gst.RtspServer {

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

#region Autogenerated code
	public partial class RTSPThread : Gst.MiniObject {

		public Gst.RtspServer.RTSPThreadType Type {
			get {
				unsafe {
					int* raw_ptr = (int*)(((byte*)Handle) + abi_info.GetFieldOffset("type"));
					return (Gst.RtspServer.RTSPThreadType) (*raw_ptr);
				}
			}
			set {
				unsafe {
					int* raw_ptr = (int*)(((byte*)Handle) + abi_info.GetFieldOffset("type"));
					*raw_ptr = (int) value;
				}
			}
		}

		public GLib.MainContext Context {
			get {
				unsafe {
					IntPtr* raw_ptr = (IntPtr*)(((byte*)Handle) + abi_info.GetFieldOffset("context"));
					return new GLib.MainContext((*raw_ptr));
				}
			}
			set {
				unsafe {
					IntPtr* raw_ptr = (IntPtr*)(((byte*)Handle) + abi_info.GetFieldOffset("context"));
					*raw_ptr = value == null ? IntPtr.Zero : value.Handle;
				}
			}
		}

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

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

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

		public bool Reuse() {
			bool raw_ret = gst_rtsp_thread_reuse(Handle);
			bool ret = raw_ret;
			return ret;
		}

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

		public void Stop() {
			gst_rtsp_thread_stop(Handle);
		}

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

		[DllImport("gstrtspserver-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_rtsp_thread_new(int type);

		public RTSPThread (Gst.RtspServer.RTSPThreadType type) : base (IntPtr.Zero)
		{
			Raw = gst_rtsp_thread_new((int) type);
		}


		// 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("type"
							, Gst.MiniObject.abi_info.Fields
							, (uint) Marshal.SizeOf(System.Enum.GetUnderlyingType(typeof(Gst.RtspServer.RTSPThreadType))) // type
							, null
							, "context"
							, (long) Marshal.OffsetOf(typeof(GstRTSPThread_typeAlign), "type")
							, 0
							),
						new GLib.AbiField("context"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // context
							, "type"
							, "loop"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("loop"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // loop
							, "context"
							, null
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
					});

				return _abi_info;
			}
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstRTSPThread_typeAlign
		{
			sbyte f1;
			private Gst.RtspServer.RTSPThreadType type;
		}


		// End of the ABI representation.

#endregion
	}
}
