/*  $Id: setupmikmod.cpp,v 1.13 2004/03/13 23:04:13 mbn Exp $
**
**  ClanLib Game SDK
**  Copyright (C) 2003  The ClanLib Team
**  For a total list of contributers see the file CREDITS.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This library is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**  Lesser General Public License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
**
*/

#include "API/MikMod/setupmikmod.h"
#include "API/MikMod/soundprovider_mikmod.h"
#include "API/Sound/SoundProviders/soundprovider_type_register.h"
#include "API/Core/Resources/resource_manager.h"
#include <mikmod.h>

static int ref_count = 0;

CL_SetupMikMod::CL_SetupMikMod(bool register_resources_only)
{
	CL_SetupMikMod::init(register_resources_only);
}

CL_SetupMikMod::~CL_SetupMikMod()
{
	CL_SetupMikMod::deinit();
}

static CL_SoundProviderType *providertype[17] = {0};

static BOOL clanMikMod_IsPresent()
{
	return 1;
}

static void clanMikMod_Update()
{
	/* do nothing */
}

/*
 * This structure is the ClanLib driver for MikMod. It's a "standard" driver
 * since it re-uses lots of functions from libMikMod, indeed the big
 * ClanLib-specific stuff is the update function, which is mapped to
 * CL_Streamed_MikModSample_Session::clanMikMod_Update
 */
MDRIVER drv_clanlib = {
	NULL,
	"clanMikMod driver",
	"0.1",
	255,
	255, 
	"clanmikmod",
	NULL, // Command line
	clanMikMod_IsPresent, // IsPresent
	VC_SampleLoad,
	VC_SampleUnload,
	VC_SampleSpace,
	VC_SampleLength,
	VC_Init,
	VC_Exit,
	NULL, // Reset
	VC_SetNumVoices,
	VC_PlayStart,
	VC_PlayStop,
	clanMikMod_Update,
	NULL, // Pause
	VC_VoiceSetVolume,
	VC_VoiceGetVolume,
	VC_VoiceSetFrequency,
	VC_VoiceGetFrequency,
	VC_VoiceSetPanning,
	VC_VoiceGetPanning,
	VC_VoicePlay,
	VC_VoiceStop,
	VC_VoiceStopped,
	VC_VoiceGetPosition,
	VC_VoiceRealVolume
};

void CL_SetupMikMod::init(bool register_resources_only)
{
	ref_count++;
	if (ref_count > 1) return;

	/* Register the loaders we want to use:  */
	MikMod_RegisterAllLoaders();
	
	/* Register the drivers we want to use: */
	MikMod_RegisterDriver(&drv_clanlib);

#ifdef WIN32
	MikMod_Init("");
#else
#if LIBMIKMOD_VERSION >= ((3 << 16) | (1 << 8) | (7))
	MikMod_Init("");
#else
	MikMod_Init();
#endif
#endif

	md_mode |= DMODE_INTERP;
	
	// disable the reverb
	md_reverb = 0;

	providertype[0] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("mikmod");
	providertype[1] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("it");
	providertype[2] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("xm");
	providertype[3] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("s3m");
	providertype[4] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("mtm");
	providertype[5] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("669");
	providertype[6] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("stm");
	providertype[7] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("ult");
	providertype[8] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("far");
	providertype[9] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("med");
	providertype[10] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("amf");
	providertype[11] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("dsm");
	providertype[12] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("imf");
	providertype[13] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("gdm");
	providertype[14] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("stx");
	providertype[15] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("okt");
	providertype[16] = new CL_SoundProviderType_Register<CL_SoundProvider_MikMod>("mod");

	/*
	 * OK, now we kind of ignore the "register_resources_only" 
	 * parameter. Indeed, MikMod_Init seems to be required for
	 * the module loader to be able to work. However, it's not
	 * a big problem since MikMod_Init() does not require any
	 * peculiar hardware and/or settings, the hardware being
	 * accessed through clanSound anyway. In fact, MikMod is
	 * only used to read modules and transform them into raw
	 * sound. Then clanSound handles everything else. So
	 * register_resources_only is of no use in this function,
	 * but is kept for API consistency.
	 */
	// if (register_resources_only) return;
}

void CL_SetupMikMod::deinit()
{
	ref_count--;
	if (ref_count > 0) return;

	for(int i=0; i<17; i++)
	{
		delete providertype[i];
		providertype[i] = 0;
	}
	
	MikMod_Exit();
}
