/*
 * $Id: base.c 4.16 1998/08/09 12:07:16 olsen Exp olsen $
 *
 * :ts=4
 *
 * Copyright © 1997-1998 Village Tronic Computer
 */

#ifndef _GLOBAL_H
#include "global.h"
#endif	/* _GLOBAL_H */

#include "Assert.h"

/****************************************************************************/

#include "concierto.audio_rev.h"

/****************************************************************************/

LONG ReturnError(VOID) { return(-1); }

/****************************************************************************/

STRPTR VersTag = VERSTAG " Copyright © 1997-1998 Village Tronic Computer";

/****************************************************************************/

STATIC struct P4AHIBase * ASM
LibInit(
	REG(a0)	BPTR				Segment,
	REG(d0) struct P4AHIBase *	P4AHIBase,
	REG(a6) struct ExecBase *	ExecBase)
{
	struct P4AHIBase *result = NULL;

	ENTER();

	P4AHIBase->ab_SysBase = ExecBase;

	if(ExecBase->LibNode.lib_Version >= 37 &&
	   (ExecBase->AttnFlags & AFF_68020) != 0)
	{
		UtilityBase	= OpenLibrary("utility.library",37);
		DOSBase		= OpenLibrary("dos.library",37);

		if(UtilityBase != NULL && DOSBase != NULL)
		{
			P4AHIBase->ab_Segment = Segment;

			P4AHIBase->ab_Library.lib_Revision = REVISION;

			InitSemaphore(&P4AHIBase->ab_LibrarySemaphore);

			InitSemaphore(&P4AHIBase->ab_DriverSemaphore);
			P4AHIBase->ab_DriverInUse = FALSE;
			P4AHIBase->ab_RecordingSource = RECORDSRC_Switcher;

			P4AHIBase->ab_TaskRunning	= FALSE;
			P4AHIBase->ab_TaskPriority	= TASK_PRIORITY_UNSET;

			P4AHIBase->ab_ReloadHook.h_Entry	= (HOOKFUNC)ReloadHookFunc;
			P4AHIBase->ab_ReloadHook.h_Data		= P4AHIBase;

			result = P4AHIBase;
		}
	}

		/* If the initialization failed, free the library
		 * base data (we have to do this on our own).
		 */

	if(result == NULL)
	{
		if(UtilityBase != NULL)
			CloseLibrary(UtilityBase);

		if(DOSBase != NULL)
			CloseLibrary(DOSBase);

		FreeMem((BYTE *)P4AHIBase - P4AHIBase->ab_Library.lib_NegSize,
		        P4AHIBase->ab_Library.lib_NegSize + P4AHIBase->ab_Library.lib_PosSize);
	}

	RETURN(result);
	return(result);
}

/****************************************************************************/

STATIC struct P4AHIBase * ASM
LibOpen(
	REG(a6) struct P4AHIBase *P4AHIBase)
{
	struct P4AHIBase *result = NULL;
	UWORD openCount;

	ENTER();

	openCount = P4AHIBase->ab_Library.lib_OpenCnt;

	P4AHIBase->ab_Library.lib_OpenCnt++;
	P4AHIBase->ab_Library.lib_Flags &= ~LIBF_DELEXP;

	SHOWMSG("ObtainSemaphore");
	ObtainSemaphore(&P4AHIBase->ab_LibrarySemaphore);

	SHOWMSG("openCount");
	if(openCount == 0)
	{
		SHOWMSG("OpenLibrary");
		ConciertoBase = OpenLibrary(CONCIERTONAME,0);

		SHOWMSG("Ok");
		SHOWVALUE(result);
	}

	if(ConciertoBase != NULL)
	{
		struct Task * thisTask;

		thisTask = FindTask(NULL);
		if(thisTask->tc_Node.ln_Type == NT_PROCESS)
		{
			UBYTE buffer[10];

			if(GetVar("concierto/ahi/priority",buffer,sizeof(buffer),0) > 0)
			{
				LONG value;

				if(StrToLong(buffer,&value) > 0)
				{
					if(-128 <= value && value <= 127)
						P4AHIBase->ab_TaskPriority = value;
				}
			}
		}

		result = P4AHIBase;
	}

	SHOWMSG("ReleaseSemaphore");
	ReleaseSemaphore(&P4AHIBase->ab_LibrarySemaphore);

	if(result == NULL)
		P4AHIBase->ab_Library.lib_OpenCnt--;

	RETURN(result);
	return(result);
}

STATIC BPTR ASM
LibExpunge(
	REG(a6) struct P4AHIBase *P4AHIBase)
{
	BPTR result = NULL;

	ENTER();

	if(P4AHIBase->ab_Library.lib_OpenCnt == 0)
	{
		CloseLibrary(UtilityBase);
		CloseLibrary(DOSBase);

		Remove((struct Node *)P4AHIBase);

		result = P4AHIBase->ab_Segment;

		FreeMem((BYTE *)P4AHIBase - P4AHIBase->ab_Library.lib_NegSize,
		        P4AHIBase->ab_Library.lib_NegSize + P4AHIBase->ab_Library.lib_PosSize);
	}
	else
	{
		P4AHIBase->ab_Library.lib_Flags |= LIBF_DELEXP;
	}

	RETURN(result);
	return(result);
}

STATIC BPTR ASM
LibClose(
	REG(a6) struct P4AHIBase *P4AHIBase)
{
	BPTR result = NULL;

	ENTER();

	ObtainSemaphore(&P4AHIBase->ab_LibrarySemaphore);

	if(P4AHIBase->ab_Library.lib_OpenCnt == 1)
	{
		CloseLibrary(ConciertoBase);
		ConciertoBase = NULL;
	}

	P4AHIBase->ab_Library.lib_OpenCnt--;

	ReleaseSemaphore(&P4AHIBase->ab_LibrarySemaphore);

	if(P4AHIBase->ab_Library.lib_OpenCnt == 0 && (P4AHIBase->ab_Library.lib_Flags & LIBF_DELEXP) != 0)
		result = LibExpunge(P4AHIBase);

	RETURN(result);
	return(result);
}

STATIC ULONG
LibReserved(VOID)
{
	return(0);
}

/****************************************************************************/

struct LibInitData
{
	ULONG	lid_LibraryBaseSize;
	APTR	lid_FunctionVector;
	APTR	lid_InitTable;
	APTR	lid_InitRoutine;
};

/****************************************************************************/

STATIC const APTR FunctionVector[] =
{
	LibOpen,
	LibClose,
	LibExpunge,
	LibReserved,

	/************************************************************************/

	LIB_AHIsub_AllocAudioA,
	LIB_AHIsub_FreeAudio,
	LIB_AHIsub_Disable,
	LIB_AHIsub_Enable,
	LIB_AHIsub_Start,
	LIB_AHIsub_Update,
	LIB_AHIsub_Stop,
	LIB_AHIsub_SetVol,
	LIB_AHIsub_SetFreq,
	LIB_AHIsub_SetSound,
	LIB_AHIsub_SetEffect,
	LIB_AHIsub_LoadSound,
	LIB_AHIsub_UnloadSound,
	LIB_AHIsub_GetAttr,
	LIB_AHIsub_HardwareControl,

	/************************************************************************/

	(APTR)-1
};

STATIC const struct LibInitData LibInitData =
{
	sizeof(struct P4AHIBase),
	FunctionVector,
	NULL,
	LibInit
};

const struct Resident LibTag =
{
	RTC_MATCHWORD,
	&LibTag,
	&LibTag + 1,
	RTF_AUTOINIT,
	VERSION,
	NT_LIBRARY,
	0,
	"concierto.audio",
	VSTRING,
	&LibInitData
};
