
/*

CLASS {AL4_OpenAL|_CSharp_via_NetCore},
	UNTESTED, NATIVE:


NATIVE: "///copy AL4_OpenAL.cs" .
NATIVE: "///copy Al.cs" .
NATIVE: "///copy Alc.cs" .


*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using OpenAL;

public static class OpenAL_Context
{


	public static List<IntPtr> All_devices = new List<IntPtr>();
	public static List<IntPtr> All_device_contexts = new List<IntPtr>();

	public static int Do_alcOpenDevice(string DevName)
	{
		IntPtr d;
		if (All_devices.Count == 0)
			All_devices.Add((IntPtr)0);
		try
		{
			if (DevName == "")
				d = Alc.OpenDevice(null);
			else d = Alc.OpenDevice(DevName);
			
			if (d == (IntPtr)0) return 0;
			for (int i = 1; i < All_devices.Count; i++)
			{
				if (All_devices[i] == null)
				{ 
					// reuse free position
					All_devices[i] = d;
					return i;
				}
			} 
			All_devices.Add((IntPtr)0);
			All_devices[All_devices.Count-1] = d;
			return All_devices.Count-1;
		}
		catch (Exception ex)
		{
			return 0;
		}
	}
	
	public static void Do_alcCloseDevice(int DevIndex)
	{
		Alc.CloseDevice(All_devices[DevIndex]);
		All_devices[DevIndex] = (IntPtr)0;
		if (DevIndex == All_devices.Count-1)
		{
			if (DevIndex == 1)
			{
				All_devices.Clear();
				return;
			}
			All_devices.RemoveAt(All_devices.Count-1);
		}
	}
	
	public static int Do_alcCreateContext(int DevIndex)
	{
		if (DevIndex == 0) return 0;
		IntPtr Ctx;
		
		IntPtr device = All_devices[DevIndex];
		Ctx = Alc.CreateContext(device, null);
		Alc.MakeContextCurrent(Ctx);
		
		for (int i = 1; i < All_device_contexts.Count; i++)
		{
			if (All_device_contexts[i] == null)
			{ 
				// reuse free position
				All_device_contexts[i] = Ctx;
				return i;
			}
		} 
		if (All_device_contexts.Count == 0)
			All_device_contexts.Add((IntPtr)0);
		All_device_contexts.Add((IntPtr)0);
		All_device_contexts[All_device_contexts.Count-1] = Ctx;
		return All_device_contexts.Count-1;
	}
	
	public static void Do_alcMakeContextCurrent(int CtxIndex)
	{
		if (CtxIndex == 0) return;
		Alc.MakeContextCurrent(All_device_contexts[CtxIndex]);
	}
	
	public static void Do_alcDestroyContext(int CtxIndex)
	{
		Alc.DestroyContext(All_device_contexts[CtxIndex]);
		All_device_contexts[CtxIndex] = (IntPtr)0;
		if (CtxIndex == All_device_contexts.Count-1)
		{
			if (CtxIndex == 1)
			{
				All_device_contexts.Clear();
				return;
			}
			All_device_contexts.RemoveAt(All_device_contexts.Count-1);
		}
	}
	
	public static IntPtr get_Device(int DevIndex)
	{
		if (DevIndex < All_device_contexts.Count)
			return All_device_contexts[DevIndex];
		else return (IntPtr)0;
	}
	
	public static void Do_Init_OpenAL()
	{
        //if (Context != (IntPtr)0)  return;
        //Context = Alc.CreateContext();
	}

}


/*

FUNCTION NATIVE_alcOpenDevice(
	STR Device_name) ==> INT, NATIVE :
	"RESULT = OpenAL_Context.Do_alcOpenDevice(X_Device_name);"
	.
	
FUNCTION NATIVE_alcCloseDevice(
	INT Dev|ice_index_1_or_higher), NATIVE
	:
	CASE Dev <= 0 ? ==> ;
	NATIVE "OpenAL_Context.Do_alcCloseDevice((int)X_Dev);" .
	
FUNCTION NATIVE_alcCreateContext(
	INT Device|_handle) ==> INT, NATIVE :
	"RESULT = OpenAL_Context.Do_alcCreateContext((int)X_Device);"
	.
	
FUNCTION NATIVE_alcDestroyContext(
	INT Context|_handle), NATIVE :
	"OpenAL_Context.Do_alcDestroyContext((int)X_Context);" .
	
FUNCTION NATIVE_alcMakeContextCurrent(
	INT Context|_handle), NATIVE :
	"OpenAL_Context.Do_alcMakeContextCurrent((int)X_Context);" .
	
	

TODO: "checking for AL presentce" .
	

CONST STR:
	NATIVE_import_OpenAL = @
	"using OpenAL;"
	
	NATIVE_OpenAL_present = @
	"RESULT = true; //todo later"
	
	NATIVE_Init_OpenAL = @
	"OpenAL_Context.Do_Init_OpenAL();"
	
	NATIVE_alcGetError = @
	"int err = 0;"
	"try {"
	"err = Alc.GetError(OpenAL_Context.get_Device((int)X_Dev));"
	"}"
	"catch {"
	"	err = 6;"     
	"}"     
	"switch (err)"
	"{"
	"case Alc.InvalidValue: RESULT = 1; break;"
	"case Alc.InvalidEnum: RESULT = 2; break;"
	"case Alc.InvalidDevice: RESULT = 3; break;"
	"case Alc.InvalidContext: RESULT = 4; break;"
	"case Alc.OutOfMemory: RESULT = 5; break;"
	"default: RESULT = (byte)err; break;"
	"}"
	
	NATIVE_alcGetString = @
	"RESULT = Alc.GetString("
	"	OpenAL_Context.get_Device((int)X_Dev), (int)X_Param);"
	
	NATIVE_alcGetIntegerv = @
	"//int[] dbuffer = new int[X_Size];"
	"//Alc.GetIntegerv(OpenAL_Context.get_Device((int)X_Dev), X_Param,"
	"//		X_Size, dbuffer);"
	"//for (int i = 0; i < X_Size; i++)"
	"//	 X_Data.set_int(i, dbuffer[i]);"
	
	NATIVE_alGetString = @
	"RESULT = Al.GetString((int)X_Param);"
	
	NATIVE_alGetBoolean = @
	"Al.GetBooleanv((int)X_Param, out RESULT);"
	
	NATIVE_alGetInteger = @
	"int r;"
	"Al.GetIntegerv((int)X_Param, out r);"
	"RESULT = r;"     
	
	NATIVE_alGetDouble = @
	"Al.GetDoublev((int)X_Param, out RESULT);"
	
	NATIVE_alGetError = @
	"int err = Al.GetError();"
	"switch(err)"
	"{"
	"case Al.InvalidName: RESULT = 1; break;"
	"case Al.InvalidEnum: RESULT = 2; break;"
	"case Al.InvalidValue: RESULT = 3; break;"
	"case Al.InvalidOperation: RESULT = 4; break;"
	"case Al.OutOfMemory: RESULT = 5; break;"
	"default: RESULT = (byte)err; break;"
	"}"
	
	NATIVE_alListenerf = @
	"Al.Listenerf((int)X_Param, (float)X_Value);"
	
	NATIVE_alGetListenerf = @
	"float[] fval;"
	"Al.GetListenerfv((int)X_Param, out fval);"
	"RESULT = fval[0];"
	
	NATIVE_alListener3f = @
	"Al.Listener3f((int)X_Param, "
	"	(float)X_Values.get_real(0),"
	"	(float)X_Values.get_real(1),"
	"	(float)X_Values.get_real(2));"
	
	NATIVE_alGetListenerfv = @
	"float[] fbuffer;"
	"Al.GetListenerfv((int)X_Param, out fbuffer);"
	"X_Values.Clear();"
	"for (int i = 0; i < fbuffer.Length; i++)"
	"	X_Values.set_real(i,  fbuffer[i]);"
	
	NATIVE_alGenSources = @
	"uint[] arr;"
	"Al.GenSources((int)X_N, out arr);"
	"for (int i = 0; i < X_N; i++)"
	"	X_Sources.set_int(i, (int)arr[i]);"
	
	NATIVE_alDeleteSources = @
	"uint[] arr = new uint[X_Sources.Count];"
	"for (int i = 0; i < X_Sources.Count; i++)"
	"	arr[i] = (uint)X_Sources.get_int(i);"
	"Al.DeleteSources(X_Sources.Count, arr);"
	
	NATIVE_alIsSource = @
	"RESULT = Al.IsSource((uint)X_Index_s);"
	
	NATIVE_alSourcef = @
	"Al.Sourcef((uint)X_Source, (int)X_Param, (float)X_Value);"
	
	NATIVE_alGetSourcef = @
	"float fvalue;"
	"Al.GetSourcef((uint)X_Source, (int)X_Param, out fvalue);"
	"RESULT = fvalue;"
	
	NATIVE_alSource3f = @
	"Al.Source3f((uint)X_Source, (int)X_Param, "
	"	(float)X_Value.get_real(0),"
	"	(float)X_Value.get_real(1),"
	"	(float)X_Value.get_real(2));"
	
	NATIVE_alGetSource3f = @
	"float f1, f2, f3;"
	"Al.GetSource3f((uint)X_Source, (int)X_Param, out f1, out f2, out f3);"
	"X_Value.set_real(0, f1);"
	"X_Value.set_real(1, f2);"
	"X_Value.set_real(2, f3);"
	
	NATIVE_alSourcei = @
	"Al.Sourcei((uint)X_Source, (int)X_Param, (int)X_Value);"
	
	NATIVE_alGetSourcei = @
	"int i;"
	"Al.GetSourcei((uint)X_Source, (int)X_Param, out i);"
	"RESULT = i;"     
	
	NATIVE_alSourcePlayv = @
	"uint[] sbuf = new uint[X_Sources.Count];"
	"for (int i = 0; i < X_Sources.Count; i++)"
	"	sbuf[i] = (uint)X_Sources.get_int(i);"
	"Al.SourcePlayv(X_Sources.Count, sbuf);"
	
	NATIVE_alSourcePausev = @
	"uint[] sbuf = new uint[X_Sources.Count];"
	"for (int i = 0; i < X_Sources.Count; i++)"
	"	sbuf[i] = (uint)X_Sources.get_int(i);"
	"Al.SourcePausev(X_Sources.Count, sbuf);"
	
	NATIVE_alSourceStopv = @
	"uint[] sbuf = new uint[X_Sources.Count];"
	"for (int i = 0; i < X_Sources.Count; i++)"
	"	sbuf[i] = (uint)X_Sources.get_int(i);"
	"Al.SourceStopv(X_Sources.Count, sbuf);"
	
	NATIVE_alSourceRewindv = @
	"uint[] sbuf = new uint[X_Sources.Count];"
	"for (int i = 0; i < X_Sources.Count; i++)"
	"	sbuf[i] = (uint)X_Sources.get_int(i);"
	"Al.SourceRewindv(X_Sources.Count, sbuf);"

	NATIVE_alSourceQueueBuffers = @
	"uint[] sbuf = new uint[X_Buffers.Count];"
	"for (int i = 0; i < X_Buffers.Count; i++)"
	"	sbuf[i] = (uint)X_Buffers.get_int(i);"
	"Al.SourceQueueBuffers((uint)X_Source, X_Buffers.Count, sbuf);"
	
	NATIVE_alSourceUnqueueBuffers = @
	"uint[] sbuf = new uint[X_Buffers.Count];"
	"Al.SourceUnqueueBuffers((uint)X_Source, X_Buffers.Count, sbuf);"
	"for (int i = 0; i < X_Buffers.Count; i++)"
	"	X_Buffers.set_int(i, (int)sbuf[i]);"
	
	NATIVE_alGenBuffers = @
	"uint[] arr;"
	"Al.GenBuffers((int)X_N, out arr);"
	"for (int i = 0; i < X_N; i++)"
	"	X_Buffers.set_int(i, (int)arr[i]);"
	
	NATIVE_alDeleteBuffers = @
	"uint[] arr = new uint[X_Buffers.Count];"
	"for (int i = 0; i < X_Buffers.Count; i++)"
	"	arr[i] = (uint)X_Buffers.get_int(i);"
	"Al.DeleteBuffers(X_Buffers.Count, arr);"
	
	NATIVE_alIsBuffer = @
	"RESULT = Al.IsBuffer((uint)X_Buffer);"
	
	NATIVE_alBufferData8 = @
	"byte[] arr =  X_Data.ToBytesArray();"
	"unsafe"
	"{"
	"	fixed( byte* parr = &arr[0] )"
	"	{"
	"	Al.BufferData((uint)X_Buffer, (int)X_Format, parr,"
	"		X_Data.Count, (int)X_Freq);"
	"	}"
	"}"
	
	NATIVE_alGetBufferiv = @
	"int vbuf;"
	"Al.GetBufferi((uint)X_Buffer, (int)X_Pname, out vbuf);"
	"X_Data.set_int(0, vbuf);"
	.

END

*/
