/*
	Steinberg Audio Stream I/O API
	(c) 1996, Steinberg Soft- und Hardware GmbH

	asio.cpp
	
	asio functions entries which translate the
	asio interface to the asiodrvr class methods
*/ 
	
#include <string.h>
#include "asiosys.h"		// platform definition
#include "asio.h"

#if MAC
#include "asiodrvr.h"

#pragma export on

AsioDriver *theAsioDriver = 0;

extern "C"
{

long main()
{
	return 'ASIO';
}

#elif WINDOWS

#include "windows.h"
#include "iasiodrv.h"
#include "asiodrivers.h"

IASIO *theAsioDriver = 0;
extern AsioDrivers *asioDrivers;

#elif SGI || SUN || BEOS || LINUX
#include "asiodrvr.h"
static AsioDriver *theAsioDriver = 0;
#endif

//-----------------------------------------------------------------------------------------------------
ASIOError ASIOInit(ASIODriverInfo *info)
{
#if MAC || SGI || SUN || BEOS || LINUX
	if(theAsioDriver)
	{
		delete theAsioDriver;
		theAsioDriver = 0;
	}		
	info->driverVersion = 0;
	strcpy(info->name, "No ASIO Driver");
	theAsioDriver = getDriver();
	if(!theAsioDriver)
	{
		strcpy(info->errorMessage, "Not enough memory for the ASIO driver!"); 
		return ASE_NotPresent;
	}
	if(!theAsioDriver->init(info->sysRef))
	{
		theAsioDriver->getErrorMessage(info->errorMessage);
		delete theAsioDriver;
		theAsioDriver = 0;
		return ASE_NotPresent;
	}
	strcpy(info->errorMessage, "No ASIO Driver Error");
	theAsioDriver->getDriverName(info->name);
	info->driverVersion = theAsioDriver->getDriverVersion();
	return ASE_OK;

#else

	info->driverVersion = 0;
	strcpy(info->name, "No ASIO Driver");
	if(theAsioDriver)	// must be loaded!
	{
		if(!theAsioDriver->init(info->sysRef))
		{
			theAsioDriver->getErrorMessage(info->errorMessage);
			theAsioDriver = 0;
			return ASE_NotPresent;
		}		

		strcpy(info->errorMessage, "No ASIO Driver Error");
		theAsioDriver->getDriverName(info->name);
		info->driverVersion = theAsioDriver->getDriverVersion();
		return ASE_OK;
	}
	return ASE_NotPresent;

#endif	// !MAC
}

ASIOError ASIOExit(void)
{
	if(theAsioDriver)
	{
#if WINDOWS
		asioDrivers->removeCurrentDriver();
#else
		delete theAsioDriver;
#endif
	}		
	theAsioDriver = 0;
	return ASE_OK;
}

ASIOError ASIOStart(void)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->start();
}

ASIOError ASIOStop(void)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->stop();
}

ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels)
{
	if(!theAsioDriver)
	{
		*numInputChannels = *numOutputChannels = 0;
		return ASE_NotPresent;
	}
	return theAsioDriver->getChannels(numInputChannels, numOutputChannels);
}

ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency)
{
	if(!theAsioDriver)
	{
		*inputLatency = *outputLatency = 0;
		return ASE_NotPresent;
	}
	return theAsioDriver->getLatencies(inputLatency, outputLatency);
}

ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity)
{
	if(!theAsioDriver)
	{
		*minSize = *maxSize = *preferredSize = *granularity = 0;
		return ASE_NotPresent;
	}
	return theAsioDriver->getBufferSize(minSize, maxSize, preferredSize, granularity);
}

ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->canSampleRate(sampleRate);
}

ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->getSampleRate(currentRate);
}

ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->setSampleRate(sampleRate);
}

ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources)
{
	if(!theAsioDriver)
	{
		*numSources = 0;
		return ASE_NotPresent;
	}
	return theAsioDriver->getClockSources(clocks, numSources);
}

ASIOError ASIOSetClockSource(long reference)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->setClockSource(reference);
}

ASIOError ASIOGetSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->getSamplePosition(sPos, tStamp);
}

ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info)
{
	if(!theAsioDriver)
	{
		info->channelGroup = -1;
		info->type = ASIOSTInt16MSB;
		strcpy(info->name, "None");
		return ASE_NotPresent;
	}
	return theAsioDriver->getChannelInfo(info);
}

ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
	long bufferSize, ASIOCallbacks *callbacks)
{
	if(!theAsioDriver)
	{
		ASIOBufferInfo *info = bufferInfos;
		for(long i = 0; i < numChannels; i++, info++)
			info->buffers[0] = info->buffers[1] = 0;
		return ASE_NotPresent;
	}
	return theAsioDriver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks);
}

ASIOError ASIODisposeBuffers(void)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->disposeBuffers();
}

ASIOError ASIOControlPanel(void)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->controlPanel();
}

ASIOError ASIOFuture(long selector, void *opt)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->future(selector, opt);
}

ASIOError ASIOOutputReady(void)
{
	if(!theAsioDriver)
		return ASE_NotPresent;
	return theAsioDriver->outputReady();
}

#if MAC
}	// extern "C"
#pragma export off
#endif